<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: James Candan</title>
    <description>The latest articles on DEV Community by James Candan (@jcandan).</description>
    <link>https://dev.to/jcandan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F82224%2F2511c25a-0c2e-46e1-bec1-baddef2c9345.jpeg</url>
      <title>DEV Community: James Candan</title>
      <link>https://dev.to/jcandan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jcandan"/>
    <language>en</language>
    <item>
      <title>Shout out to freeCodeCamp's distraction-free VS Code settings</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Mon, 27 Jan 2025 15:39:28 +0000</pubDate>
      <link>https://dev.to/jcandan/shout-out-to-freecodecamps-distraction-free-vs-code-settings-nag</link>
      <guid>https://dev.to/jcandan/shout-out-to-freecodecamps-distraction-free-vs-code-settings-nag</guid>
      <description>&lt;p&gt;Inspired by freeCodeCamp's use of CodeRoad, while building tutorials for Stack Elevate, I came across this gem: a distraction-free VS Code settings configuration.&lt;/p&gt;

&lt;p&gt;This is perfect for students engaged in a provided-for-you development environment, to create an engaging, distraction-free coding environment. Good for minimalists too, but may not be suited for those ready to take on the day-to-day work of software development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .vscode/settings.json
{
  "breadcrumbs.enabled": false,
  "debug.internalConsoleOptions": "neverOpen",
  "debug.showInStatusBar": "never",
  "editor.acceptSuggestionOnCommitCharacter": false,
  "editor.acceptSuggestionOnEnter": "off",
  "editor.autoClosingBrackets": "never",
  "editor.codeActionsOnSave": {
    "source.fixAll": "explicit"
  },
  "editor.hover.enabled": false,
  "editor.inlineSuggest.enabled": false,
  "editor.minimap.enabled": false,
  "editor.parameterHints.enabled": false,
  "editor.quickSuggestions": {
    "other": false,
    "comments": false,
    "strings": false
  },
  "editor.referenceInfos": false,
  "editor.snippetSuggestions": "none",
  "editor.suggest.statusBar.visible": false,
  "editor.suggestOnTriggerCharacters": false,
  "editor.tabSize": 2,
  "explorer.autoReveal": false,
  "explorer.openEditors.visible": 0,
  "extensions.autoCheckUpdates": false,
  "extensions.ignoreRecommendations": true,
  "files.autoSave": "afterDelay",
  "files.exclude": {
    "**/.git": true,
    "**/.svn": true,
    "**/.hg": true,
    "**/CVS": true,
    "**/.DS_Store": true,
    ".vscode": true,
    ".gitignore": true,
    "freeCodeCamp": true,
    "learn-bash-by-building-a-boilerplate": true,
    ".gitpod.Dockerfile": true,
    ".gitpod.yml": true,
    "CHANGELOG.md": true,
    "coderoad.yaml": true,
    "tutorial.json": true,
    "TUTORIAL.md": true
  },
  "html.autoClosingTags": false,
  "npm.fetchOnlinePackageInfo": false,
  "task.slowProviderWarning": false,
  "terminal.integrated.allowChords": false,
  "terminal.integrated.commandsToSkipShell": ["coderoad.enter"],
  "terminal.integrated.enableFileLinks": false,
  "terminal.integrated.environmentChangesIndicator": "off",
  "terminal.integrated.macOptionIsMeta": true,
  "terminal.integrated.showExitAlert": false,
  "telemetry.enableTelemetry": false,
  "update.mode": "none",
  "update.showReleaseNotes": false,
  "workbench.enableExperiments": false,
  "workbench.startupEditor": "none",
  "workbench.colorTheme": "Tomorrow Night Blue",
  "workbench.colorCustomizations": {
    "[Tomorrow Night Blue]": {
      "menu.background": "#0a0a23",
      "menu.foreground": "#ffffff",
      "activityBar.background": "#0a0a23",
      "activityBar.foreground": "#ffffff",
      "activityBar.activeBorder": "#ffffff",
      "activityBar.border": "#2a2a40",
      "editorWidget.background": "#0a0a23",
      "editorWidget.foreground": "#ffffff",
      "sideBar.background": "#1b1b32",
      "sideBarTitle.foreground": "#858591",
      "sideBar.foreground": "#f5f6f7",
      "sideBar.border": "#2a2a40",
      "editor.background": "#2a2a40",
      "editor.foreground": "#dfdfe2",
      "tab.activeForeground": "#ffffff",
      "tab.inactiveBackground": "#1b1b32",
      "tab.inactiveForeground": "#d0d0d5",
      "tab.border": "#2a2a40",
      "editorGroupHeader.tabsBackground": "#0a0a23",
      "editorIndentGuide.background": "#3b3b4f",
      "terminal.background": "#0a0a23",
      "terminal.foreground": "#ffffff",
      "terminal.ansiBrightGreen": "#ffffff",
      "panel.background": "#1b1b32",
      "panelTitle.inactiveForeground": "#858591",
      "panelTitle.activeBorder": "#f5f6f7"
    }
  },
  "workbench.iconTheme": null,
  "workbench.statusBar.visible": false,
  "workbench.tips.enabled": false,
  "workbench.tree.renderIndentGuides": "none",
  "zenMode.centerLayout": false
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;source: &lt;a href="https://github.com/freeCodeCamp/learn-bash-by-building-a-boilerplate/blob/main/.vscode/settings.json" rel="noopener noreferrer"&gt;freeCodeCamp: learn-bash-by-building-a-boilerplate: .vscode/settings.json&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Here’s a detailed breakdown of the provided VS Code &lt;code&gt;settings.json&lt;/code&gt; configuration, as summarized by ChatGPT:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;General Settings&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;breadcrumbs.enabled&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables the breadcrumb navigation bar at the top of the editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;debug.internalConsoleOptions&lt;/code&gt;: &lt;code&gt;neverOpen&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Prevents the debug console from automatically opening during a debugging session.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;debug.showInStatusBar&lt;/code&gt;: &lt;code&gt;never&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hides the debug status bar item.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Editor Behavior&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.acceptSuggestionOnCommitCharacter&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Prevents auto-completion when pressing commit characters (e.g., &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;,&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.acceptSuggestionOnEnter&lt;/code&gt;: &lt;code&gt;off&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables accepting suggestions by pressing &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.autoClosingBrackets&lt;/code&gt;: &lt;code&gt;never&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables automatic closing of brackets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.codeActionsOnSave&lt;/code&gt;: &lt;code&gt;{ "source.fixAll": "explicit" }&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Runs all applicable code fixes explicitly marked as fixable on save.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.hover.enabled&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables the hover tooltip feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.inlineSuggest.enabled&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables inline suggestions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.minimap.enabled&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables the minimap (code overview bar).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.parameterHints.enabled&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables parameter hints when typing function arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.quickSuggestions&lt;/code&gt;: &lt;code&gt;{ "other": false, "comments": false, "strings": false }&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables suggestions in all contexts: other code, comments, and strings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.referenceInfos&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables reference information in the editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.snippetSuggestions&lt;/code&gt;: &lt;code&gt;none&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables snippet suggestions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.suggest.statusBar.visible&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hides the suggestion widget status bar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.suggestOnTriggerCharacters&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables suggestions triggered by specific characters (e.g., &lt;code&gt;.&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;editor.tabSize&lt;/code&gt;: &lt;code&gt;2&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sets the tab width to 2 spaces.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Explorer and Files&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;explorer.autoReveal&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Prevents automatically revealing the active file in the file explorer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;explorer.openEditors.visible&lt;/code&gt;: &lt;code&gt;0&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hides the "Open Editors" section in the explorer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;files.autoSave&lt;/code&gt;: &lt;code&gt;afterDelay&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Saves files automatically after a short delay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;files.exclude&lt;/code&gt;: &lt;code&gt;{ ... }&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hides specific files and folders from the explorer, including &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;.vscode&lt;/code&gt;, &lt;code&gt;.DS_Store&lt;/code&gt;, and several specific files like &lt;code&gt;CHANGELOG.md&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Extensions&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;extensions.autoCheckUpdates&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables automatic extension update checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;extensions.ignoreRecommendations&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ignores extension recommendations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;HTML and NPM&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;html.autoClosingTags&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables automatic closing of HTML tags.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;npm.fetchOnlinePackageInfo&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Prevents fetching online package info when working with &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Terminal Settings&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal.integrated.allowChords&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables key chord detection in the terminal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal.integrated.commandsToSkipShell&lt;/code&gt;: &lt;code&gt;["coderoad.enter"]&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Skips processing &lt;code&gt;coderoad.enter&lt;/code&gt; command in the shell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal.integrated.enableFileLinks&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables clickable file links in the terminal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal.integrated.environmentChangesIndicator&lt;/code&gt;: &lt;code&gt;off&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables indicators for environment variable changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal.integrated.macOptionIsMeta&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Treats the &lt;code&gt;Option&lt;/code&gt; key as &lt;code&gt;Meta&lt;/code&gt; on macOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal.integrated.showExitAlert&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables alerts when a terminal process exits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Telemetry and Updates&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;telemetry.enableTelemetry&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables telemetry data collection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;update.mode&lt;/code&gt;: &lt;code&gt;none&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables automatic updates for VS Code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;update.showReleaseNotes&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Prevents showing release notes after an update.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Workbench Settings&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.enableExperiments&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables experimental features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.startupEditor&lt;/code&gt;: &lt;code&gt;none&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Prevents the startup editor (welcome page) from opening.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.colorTheme&lt;/code&gt;: &lt;code&gt;Tomorrow Night Blue&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sets the color theme to "Tomorrow Night Blue."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.colorCustomizations&lt;/code&gt;: &lt;code&gt;{ ... }&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Customizes the colors for the selected theme (e.g., background, foreground, sidebar, tabs, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.iconTheme&lt;/code&gt;: &lt;code&gt;null&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables the file icon theme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.statusBar.visible&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hides the status bar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.tips.enabled&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables tips and recommendations in the workbench.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;workbench.tree.renderIndentGuides&lt;/code&gt;: &lt;code&gt;none&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Disables indent guides in tree views.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Zen Mode&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;zenMode.centerLayout&lt;/code&gt;: &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;
Prevents centering the editor layout in Zen mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This configuration is designed to &lt;strong&gt;minimize distractions&lt;/strong&gt; by disabling most UI elements, suggestions, and automatic behaviors. It’s ideal for users who prefer a clean, highly customized workspace focused solely on code. Let me know if you'd like further details on any specific part!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;VS Code Minimalist Configuration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This &lt;code&gt;settings.json&lt;/code&gt; file is designed to create a &lt;strong&gt;clean, distraction-free coding environment&lt;/strong&gt; for developers, educators, or learners who prefer simplicity and focus. It disables many of VS Code’s default features that might feel overwhelming or unnecessary, allowing you to concentrate on the code itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Distraction-Free Editor&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removes extra visual elements like the minimap, breadcrumbs, and hover tooltips.
&lt;/li&gt;
&lt;li&gt;Disables inline suggestions, auto-closing brackets, and parameter hints to avoid interruptions.
&lt;/li&gt;
&lt;li&gt;Keeps the interface simple by hiding the status bar and startup editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Streamlined Workflow&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Focuses on manual control by turning off auto-completion, suggestion pop-ups, and snippet suggestions.
&lt;/li&gt;
&lt;li&gt;Simplifies the explorer by hiding unnecessary files and folders (e.g., &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;.vscode&lt;/code&gt;, temporary files).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Privacy and Stability&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disables telemetry (tracking and data sharing with VS Code).
&lt;/li&gt;
&lt;li&gt;Prevents automatic updates to extensions or the editor itself, ensuring a consistent experience.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom Theme and Appearance&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses the &lt;strong&gt;Tomorrow Night Blue&lt;/strong&gt; theme, a dark and low-contrast color scheme that’s easy on the eyes.
&lt;/li&gt;
&lt;li&gt;Further customizes the theme for a cohesive and polished look (e.g., sidebar, tabs, terminal colors).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terminal Tweaks&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjusts terminal behavior for simplicity, like disabling clickable links and environment change notifications.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Who Is This For?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This setup is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developers who prefer minimalism:&lt;/strong&gt; Perfect if you want to focus on writing code without the noise of extra features.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Educators or workshop hosts:&lt;/strong&gt; Simplifies the interface, making it easier for learners to follow along without distractions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy-conscious users:&lt;/strong&gt; Reduces data sharing and unnecessary online activity from the editor.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Those maintaining legacy projects or tutorials:&lt;/strong&gt; Optimized for working in environments with specific file structures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How It Feels to Use&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You’ll notice fewer pop-ups, suggestions, and visual elements cluttering your screen.
&lt;/li&gt;
&lt;li&gt;The editor stays calm and focused, encouraging manual coding and problem-solving rather than relying on hints or automation.
&lt;/li&gt;
&lt;li&gt;It feels lightweight and stable, making it an excellent choice for long coding sessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Customizations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This configuration has been tailored with specific preferences in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certain files and folders (like &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;.DS_Store&lt;/code&gt;, and FreeCodeCamp-related files) are hidden from the file explorer.
&lt;/li&gt;
&lt;li&gt;The terminal and editor are simplified, but basic functionality remains intact.
&lt;/li&gt;
&lt;li&gt;The color scheme is soothing and consistent, designed for extended use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How to Use This Configuration&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Copy the contents of &lt;code&gt;settings.json&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Open VS Code and go to &lt;code&gt;File &amp;gt; Preferences &amp;gt; Settings&lt;/code&gt; (or press &lt;code&gt;Ctrl + ,&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Click the &lt;code&gt;{}&lt;/code&gt; icon in the top-right corner to open the settings editor in JSON format.
&lt;/li&gt;
&lt;li&gt;Paste the configuration and save the file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Enjoy a cleaner, distraction-free coding experience!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A ChatGPT About Drupal Conventional Commits</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Tue, 02 May 2023 16:04:13 +0000</pubDate>
      <link>https://dev.to/jcandan/drupal-conventional-commits-opg</link>
      <guid>https://dev.to/jcandan/drupal-conventional-commits-opg</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I have implemented Semantic Releases and an autogenerated Change Log into Drupal projects. The effort has surprised me at times, thinking about what a commit message should be categorized as, whether it should be noted in the change log, how and whether it affects a release version bump, and whether it is appropriate to squash merge requests.&lt;/p&gt;

&lt;p&gt;Since I haven't found any forum posts, issues, or articles on this problem space as it relates to CMSs generally and to Drupal projects specifically, I decided to pick ChatGPT's brain on the subject. The following is the result of this conversation.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Chat About Drupal Conventional Commits
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;What are conventional commits?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Conventional Commits is a specification for structuring commit messages in a standardized way. The idea is to make it easier for developers to understand the purpose and context of a commit, and to automate certain parts of the software development process, such as generating changelogs or triggering automatic deployments.&lt;/p&gt;

&lt;p&gt;A conventional commit message consists of a header, a body, and a footer. The header includes a type, a scope, and a subject, which together describe the change being made. The body and footer are optional and provide additional information about the change.&lt;/p&gt;

&lt;p&gt;The type of a commit message is a keyword that specifies the general nature of the change. For example, the type might be "feat" for a new feature, "fix" for a bug fix, or "docs" for documentation updates. The scope is optional and is used to further specify the location or component of the change, such as a specific file or module.&lt;/p&gt;

&lt;p&gt;Here's an example of a conventional commit message:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(authentication): add support for OAuth2 authentication

This commit adds support for OAuth2 authentication using the Google API.

BREAKING CHANGE: The previous authentication method has been removed.
In this example, the type is "feat", the scope is "authentication", and the subject is "add support for OAuth2 authentication". The body provides additional details about the change, and the footer includes a "BREAKING CHANGE" section indicating that the change is backwards-incompatible.
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;By following the Conventional Commits specification, developers can ensure that their commit messages are consistent, informative, and machine-readable, making it easier to collaborate and automate certain parts of the software development process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;I can see how this can be useful to autogenerate a change log. That might work for libraries or packages. But, is this applicable to web applications and content management systems?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, Conventional Commits can be used for web applications and content management systems as well, especially if they are built using a version control system such as Git.&lt;/p&gt;

&lt;p&gt;In web development, changes to the codebase can have a direct impact on the user experience, and it's important to be able to communicate those changes effectively to users, stakeholders, and other developers. By using a standardized commit message format, such as Conventional Commits, developers can provide more context and clarity around the changes they are making, which can help reduce confusion and improve collaboration.&lt;/p&gt;

&lt;p&gt;For example, if a developer is working on a web application and makes a change to the login process, they might use a commit message like this:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(login): add support for two-factor authentication

This commit adds support for two-factor authentication to the login process, improving security for users.

BREAKING CHANGE: Users will need to set up two-factor authentication before logging in.
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This message makes it clear that the change is related to the login process, what the change is (adding two-factor authentication), why the change is important (improving security), and any breaking changes that might affect users (they will need to set up two-factor authentication before logging in).&lt;/p&gt;

&lt;p&gt;By using Conventional Commits, developers can create commit messages that are consistent, informative, and easy to understand, making it easier to collaborate and manage changes to web applications and content management systems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Semantic Release is an NPM package with plugins that can generate release notes based on commit messages. By default, it treats breaking changes as major, feature enhancements as minor, and bug fixes as patch releases. Angular has its own set of conventional commit types for web applications. What are some appropriate commit types for a CMS? And how might each affect the release version?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;The appropriate commit types for a CMS will depend on the specific features and functionality of the CMS, but here are some common types of commits that may be applicable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;feat&lt;/strong&gt;: This commit type can be used for new features or functionality added to the CMS. Depending on the significance of the feature, it could result in a minor or major release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fix&lt;/strong&gt;: This commit type can be used for bug fixes within the CMS. This would typically result in a patch release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docs&lt;/strong&gt;: This commit type can be used for documentation changes, such as updating the user manual or adding inline comments. This type of commit would not usually affect the release version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;style&lt;/strong&gt;: This commit type can be used for changes to the look and feel of the CMS, such as updating the CSS or layout. This type of commit would not usually affect the release version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;refactor&lt;/strong&gt;: This commit type can be used for code changes that do not add any new functionality or fix any bugs, but are done for other reasons such as improving code readability or maintainability. This type of commit would not usually affect the release version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;test&lt;/strong&gt;: This commit type can be used for changes to the testing infrastructure, such as adding new unit tests or fixing broken tests. This type of commit would not usually affect the release version.&lt;/p&gt;

&lt;p&gt;In terms of how each type of commit might affect the release version, it would depend on the specific rules and guidelines set by the CMS development team. Typically, breaking changes would result in a major release, new features would result in a minor release, and bug fixes would result in a patch release. However, this may vary depending on the significance of the changes and the development team's release management process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Do style, docs, refactor, and test types typically affect the release version?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;In general, commit types like style, docs, refactor, and test are not expected to have a significant impact on the release version of a project. These commit types are typically considered as non-breaking changes, as they don't add new features, fix bugs, or change the behavior of the software.&lt;/p&gt;

&lt;p&gt;However, in some cases, these types of changes may indirectly impact the release version. For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;style&lt;/strong&gt;: Changes to the style or formatting of the code may affect the behavior of the software, particularly if there are syntax errors introduced. While unlikely, it's possible that such changes may require a patch release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docs&lt;/strong&gt;: Changes to documentation are usually independent of the software functionality and shouldn't affect the release version, unless the documentation is incorrect, incomplete, or unclear and is causing issues for the users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;refactor&lt;/strong&gt;: Changes to code structure, organization, or naming conventions don't usually change the functionality of the software, but in some cases, they may indirectly impact the behavior of the software. For example, refactoring may remove duplicate code, which could affect performance or memory usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;test&lt;/strong&gt;: Changes to the test suite shouldn't impact the release version, as long as they don't introduce new bugs or issues that are not caught during the testing phase.&lt;/p&gt;

&lt;p&gt;Ultimately, the decision of whether a particular commit should trigger a release or not depends on the project's specific release management process and guidelines. The release manager should consider the impact of each commit on the software, the severity of the changes, and the project's release schedule to decide whether a new release is necessary or not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;So, the default behavior from Semantic Release's plugin should be configured to treat each type's release version change as appropriate for the project. The Drupal ecosystem has a number of possible software projects associated with it: modules, NPM packages, composer packages, etc. When each is developed independently, I can see how semantic versioning and commit types can be used very clearly. It is not so clear for Drupal CMS projects as a whole. A CMS project has several types of end users and stake holders. If the change log is meant to communicate to editors and possibly site visitors, what conventional commit types do you think might be most appropriate?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;For Drupal CMS projects that are meant to be used by multiple types of end users and stakeholders, the commit types should be selected carefully to ensure that the release notes are easy to understand and useful for all stakeholders. Here are some commit types that might be most appropriate:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;feat&lt;/strong&gt;: This commit type can be used for new features or functionality that are relevant to end users or stakeholders. For example, adding a new content type or user role could be considered a feature that should be communicated to stakeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fix&lt;/strong&gt;: This commit type can be used for bug fixes that are relevant to end users or stakeholders. For example, fixing a broken link or resolving a permission issue could be considered a fix that should be communicated to stakeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docs&lt;/strong&gt;: This commit type can be used for changes to documentation that are relevant to end users or stakeholders. For example, updating the user manual or adding inline help text could be considered a documentation change that should be communicated to stakeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;style&lt;/strong&gt;: This commit type can be used for changes to the look and feel of the CMS that are relevant to end users or stakeholders. For example, updating the color scheme or typography could be considered a style change that should be communicated to stakeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;refactor&lt;/strong&gt;: This commit type can be used for code changes that improve the CMS's performance, security, or maintainability, which may not be immediately visible to end users but still have an impact on their experience. For example, optimizing database queries or refactoring legacy code could be considered a refactor that should be communicated to stakeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;chore&lt;/strong&gt;: This commit type can be used for changes to the build process, dependencies, or other non-functional aspects of the CMS that are relevant to developers or site administrators. For example, upgrading to a new version of PHP or updating a third-party library could be considered a chore that should be communicated to stakeholders.&lt;/p&gt;

&lt;p&gt;Ultimately, the choice of commit types depends on the specific features and functionality of the CMS and the priorities of its stakeholders. The goal should be to provide clear and concise release notes that communicate the changes in a way that is relevant and useful to all stakeholders.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;What about development specific features? For example, we are adding a set of modules and configurations for local development of a data migration. This doesn't affect editors or site visitors, but lays the groundwork for developers to begin building custom data migration tools. What commit type seems most appropriate here?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;For development-specific features like adding modules and configurations for local development of a data migration, the most appropriate commit type would be &lt;code&gt;feat&lt;/code&gt;, as it represents the addition of new features or functionality. Specifically, you could use a prefix to distinguish the commit as being relevant to developers only, such as &lt;code&gt;dev-feat&lt;/code&gt; or &lt;code&gt;internal-feat&lt;/code&gt;. This communicates to stakeholders that the commit is related to a feature that is only relevant to the development team, and not to end users or site visitors.&lt;/p&gt;

&lt;p&gt;While this commit type may not directly impact the CMS's end users or stakeholders, it is still important to communicate these changes in the release notes to keep everyone informed and up-to-date with the progress of the project. This also helps to build transparency and trust within the development team and with external stakeholders who may be interested in the project's development process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Should a refactor affect the release version--major, minor, patch, or none?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Whether a refactor should affect the release version depends on the scope and impact of the changes made. In general, refactors that have a significant impact on the functionality or stability of the codebase should result in a version change. However, if the refactor only improves the code quality or maintainability without changing the external behavior of the system, then it might not require a version change.&lt;/p&gt;

&lt;p&gt;If the refactor introduces new features or breaks existing ones, it should result in a major version change. If it includes performance improvements or adds functionality in a backward-compatible way, it should result in a minor version change. If the refactor only fixes bugs or includes small improvements, it should result in a patch version change.&lt;/p&gt;

&lt;p&gt;It's important to note that the decision to increment the version number should be made based on the impact of the refactor on the external behavior of the system, rather than the effort put into the refactor. The version number should accurately reflect the changes made and the impact they have on the system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;How can we tell semantic release to treat refactor commits differently?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;To tell Semantic Release to treat refactor commits differently, you can use a custom configuration for the @semantic-release/commit-analyzer plugin. This plugin is responsible for analyzing the commit messages and determining the appropriate version number to assign to the release. By default, it treats refactors as patch releases, but you can customize this behavior by configuring the plugin to consider refactor commits as minor or major releases instead.&lt;/p&gt;

&lt;p&gt;To do this, you can use the "preset" option in your semantic-release configuration file and specify a custom commit message preset that defines how refactor commits should be handled. For example, you could create a custom preset that treats refactor commits as minor releases by adding the following to your configuration file:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "preset": "angular",
  "plugins": [
    "@semantic-release/commit-analyzer",
    {
      "preset": "angular",
      "releaseRules": [
        {"type": "refactor", "release": "minor"}
      ]
    },
    "@semantic-release/release-notes-generator",
    "@semantic-release/github"
  ]
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In this configuration, we're using the "angular" preset as a base, which defines the default behavior for commit types. Then, we're configuring the commit analyzer plugin to consider refactor commits as minor releases by adding a custom release rule that matches commits with the "refactor" type and sets the release type to "minor".&lt;/p&gt;

&lt;p&gt;With this configuration, Semantic Release will assign a minor version number to any release that includes a commit with the "refactor" type, as long as there are no other breaking changes or major features included in the release.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Are there any commits that should skip a release version change?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, there are certain types of commits that may not require a release version change. For example, commits that only update documentation, code formatting, comments, or other non-functional changes that don't impact the system's behavior or features may not need to trigger a new release version.&lt;/p&gt;

&lt;p&gt;In general, any commit that doesn't add new functionality or modify existing functionality in a significant way could be considered a candidate for skipping a release version change. However, it's ultimately up to the project team to decide which types of commits should trigger a version change and which should not.&lt;/p&gt;

&lt;p&gt;It's worth noting that skipping a release version change for certain commits can be a useful strategy for avoiding unnecessary version number increments, especially for projects with frequent releases or small changes. This can help to prevent confusion among users and stakeholders who may expect major version increments to signal significant changes or new features. On the other hand, if a commit does impact the system's behavior or features in a meaningful way, it's important to update the version number accordingly to ensure clarity and transparency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Me:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;When is it appropriate to bump a major version of a CMS website? Is it appropriate to consider removing a feature a breaking change? This is not an API, it's a web application provided to editors in order to communicate with site visitors. What might be considered a breaking change for a CMS website? Should the site's major version only be bumped if a strong visual or organizational change is made?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ChatGPT
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;In a CMS website, it's appropriate to bump a major version when there are significant changes that affect the overall functionality, usability, or compatibility of the website. Some examples of changes that might warrant a major version bump include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing a core feature that is widely used by site editors or visitors&lt;/li&gt;
&lt;li&gt;Changing the way that content is structured or displayed, such as reorganizing menus or changing the layout of pages&lt;/li&gt;
&lt;li&gt;Upgrading to a new major version of the CMS software itself, which may introduce significant changes to the underlying architecture or APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, any change that significantly impacts the user experience or requires significant effort for editors or developers to adapt to could be considered a candidate for a major version bump.&lt;/p&gt;

&lt;p&gt;Regarding removing a feature, it depends on the feature itself and how widely it is used. If it's a core feature that many editors or visitors rely on, removing it could be considered a breaking change. However, if it's a less frequently used feature or one that can be replaced with a similar feature, it may not be necessary to consider it a breaking change.&lt;/p&gt;

&lt;p&gt;It's important to communicate any breaking changes clearly to editors and other stakeholders and to provide guidance on how to adapt to the changes. In some cases, it may be appropriate to provide a transitional period where both the old and new features are available, to allow users to adjust at their own pace.&lt;/p&gt;

&lt;p&gt;As for when to bump the major version of the site, it's ultimately up to the project team to decide based on the scope and impact of the changes being made. If there are strong visual or organizational changes that significantly affect the user experience or require a significant amount of effort to adapt to, then it may be appropriate to bump the major version. However, if the changes are more incremental or focused on bug fixes and minor enhancements, it may be more appropriate to bump the minor or patch version instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This was a fun exercise. I do hope to nail down and contribute a &lt;code&gt;conventional-changelog-drupal&lt;/code&gt; package one day.  In the meantime, I suggest you familiarize yourself with the default &lt;a href="https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular" rel="noopener noreferrer"&gt;Angular change log preset&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Do leave comments giving me your thoughts. Hopefully, we can come up with a shared convention that makes sense for broader CMS web implementations. Again, this is a challenge, not for libraries, packages, distributions, or frameworks--all of which I think are covered well in the available online discussion on the topic--, but for the implementation of a web CMS project: the thing that is released, deployed, and edited by editors on production and contains content meant for a website visitor. It seems there are several layers of stakeholders. How do we communicate release changes to each in a way that makes sense to them?&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>chatgpt</category>
      <category>git</category>
      <category>devops</category>
    </item>
    <item>
      <title>Drupal 9+ SEO</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Sat, 22 Apr 2023 16:20:16 +0000</pubDate>
      <link>https://dev.to/jcandan/drupal-9-seo-3gec</link>
      <guid>https://dev.to/jcandan/drupal-9-seo-3gec</guid>
      <description>&lt;p&gt;A while back, the &lt;a href="https://www.drupal.org/project/varbase" rel="noopener noreferrer"&gt;Varbase&lt;/a&gt; distribution turned me on to &lt;a href="https://www.drupal.org/project/yoast_seo" rel="noopener noreferrer"&gt;Real-time SEO for Drupal&lt;/a&gt; for SEO analysis in Drupal. &lt;/p&gt;

&lt;p&gt;However, I recently tried it out for a Drupal 9 project, and it failed to capture Layout Builder content. Also, it has a 2.0-alpha that's been halted.&lt;/p&gt;

&lt;p&gt;I just found this gem, and it does the trick really well, even with Layout Builder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drupal.org/project/yoast_analysis" rel="noopener noreferrer"&gt;Yoast Analysis &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ppx23qliqph3kxp4q5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ppx23qliqph3kxp4q5k.png" alt="Image description" width="800" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It supports Drupal 9 and Drupal 10.&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>seo</category>
    </item>
    <item>
      <title>Drupal Install with Configs and hook_install()</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Tue, 04 Apr 2023 21:15:55 +0000</pubDate>
      <link>https://dev.to/jcandan/drupal-install-with-configs-and-hookinstall-4112</link>
      <guid>https://dev.to/jcandan/drupal-install-with-configs-and-hookinstall-4112</guid>
      <description>&lt;p&gt;I was able to perform the following steps to fix a config dependency error and then do a fresh install &lt;strong&gt;with config&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;First, in order to bypass the &lt;code&gt;--existing-config&lt;/code&gt; restriction on install profiles with a &lt;code&gt;hook_install()&lt;/code&gt;, comment out &lt;code&gt;web/core/profiles/standard/standard.install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# A clean install to work with
lando drush si standard -y

# Export any individual missing configs.
# Example:
lando drush config:get comment.type.comment &amp;gt; config/sync/comment.type.comment.yml
lando drush config:get field.field.comment.comment.comment_body &amp;gt; config/sync/field.field.comment.comment.comment_body.yml

# Re-install with existing configs.
lando drush si standard --existing-config -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you have a working Drupal install with the imported existing configs.&lt;/p&gt;

&lt;p&gt;We still want to run the standard profile's installation hook. So, copy the contents of &lt;code&gt;standard_install()&lt;/code&gt;. In a text editor, paste and edit the PHP statements. Ensure the full paths are supplied to the class names. Copy this set of statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  $user = User::load(1);
&lt;/span&gt;&lt;span class="gi"&gt;+  $user = Drupal\user\Entity\User::load(1);
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;-  $shortcut = Shortcut::create([
&lt;/span&gt;&lt;span class="gi"&gt;+  $shortcut = Drupal\shortcut\Entity\Shortcut::create([
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;-  $shortcut = Shortcut::create([
&lt;/span&gt;&lt;span class="gi"&gt;+  $shortcut = Drupal\shortcut\Entity\Shortcut::create([
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hop into a PHP REPL, paste and run the PHP statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ lando drush php
Psy Shell v0.10.12 (PHP 8.0.27 — cli) by Justin Hileman
Caonline Rebuild - Workbench Access (Drupal 9.4.5)
&amp;gt;&amp;gt;&amp;gt;   $user = Drupal\user\Entity\User::load(1);
...
  $shortcut-&amp;gt;save();
=&amp;gt; 1
&amp;gt;&amp;gt;&amp;gt; exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you can export configs and commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lando drush cex -y 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Secure SSO with Drupal</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Wed, 22 Mar 2023 10:53:11 +0000</pubDate>
      <link>https://dev.to/jcandan/secure-sso-with-drupal-32f</link>
      <guid>https://dev.to/jcandan/secure-sso-with-drupal-32f</guid>
      <description>&lt;p&gt;SimpleSAMLphp in Drupal is great, but documentation around a &lt;em&gt;secure&lt;/em&gt; setup is lacking. So, here's that.&lt;/p&gt;

&lt;p&gt;tldr;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a &lt;code&gt;SIMPLESAMLPHP_CONFIG_DIR&lt;/code&gt; environment variable to point to a committed config directory (typically, I set it to &lt;code&gt;config/simplesaml/config&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In that config directory, copy the the appropriate template config files with the sensitive data set to look at environment variables (e.g. Replace the original &lt;code&gt;saml20-idp-remote.php&lt;/code&gt; hash value with &lt;code&gt;getenv('SIMEPLE_SAML_METADATA_CERT_KEY')&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;supply saml.crt and saml.pem SSL uncommitted certs to the certdir configured in config/simplesamlphp/config/config.php.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Full-width, Drupal core Remote Video with YouTube parameters</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Thu, 05 Jan 2023 05:52:50 +0000</pubDate>
      <link>https://dev.to/jcandan/full-width-drupal-core-remote-video-with-youtube-parameters-12kf</link>
      <guid>https://dev.to/jcandan/full-width-drupal-core-remote-video-with-youtube-parameters-12kf</guid>
      <description>&lt;p&gt;Drupal core supplies us a Remote Video media type. To display Media items of this type in a block, full-width, with desired YouTube parameters, you'll need the following.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This was tested on Drupal 10 in January 2023. The latest FitVids library release is 1.2.0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Modules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entity Block&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  composer require drupal/entity_block
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entity Block will allow you to add Remote Videos to a Layout Builder section block.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FitVids&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  composer require drupal/fitvids
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The FitVids module relies on a package that detects video embeds and widens them to fill their respective HTML container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A custom module for YouTube parameter handling&lt;/strong&gt;
Drupal core's oEmbed &lt;a href="https://www.drupal.org/project/drupal/issues/3218217" rel="noopener noreferrer"&gt;does not currently&lt;/a&gt; support &lt;a href="https://developers.google.com/youtube/player_parameters" rel="noopener noreferrer"&gt;YouTube Embedded Players and Player Parameters&lt;/a&gt;. We'll need a custom module to make this happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips and Additional Bits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  FitVids Library
&lt;/h3&gt;

&lt;p&gt;The FitVids module will require you to have the FitVids library. This has not been released to Packagist. So, we'll need to specify a special package repository in Composer.&lt;/p&gt;

&lt;p&gt;To get the FitVids library, add this to your &lt;code&gt;composer.json&lt;/code&gt;, within your &lt;code&gt;repositories&lt;/code&gt; list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"package"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"package"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"davatron5000/fitvids"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"drupal-library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/davatron5000/FitVids.js.git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v1.2.0"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"composer/installers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"extra"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"installer-name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fitvids"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require davatron5000/fitvids:1.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  FitVids oEmbed Patch
&lt;/h3&gt;

&lt;p&gt;Add the &lt;a href="https://www.drupal.org/project/fitvids/issues/3158833" rel="noopener noreferrer"&gt;Not applying to oEmbed videos&lt;/a&gt; patch (as of this writing, tested successfully with comment #2's patch).&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure FitVids for youtu.be
&lt;/h3&gt;

&lt;p&gt;FitVids doesn't recognize the &lt;a href="https://youtu.be" rel="noopener noreferrer"&gt;https://youtu.be&lt;/a&gt; embed URL, but the module allows us to fix that.&lt;/p&gt;

&lt;p&gt;Simply add a FitVids setting for custom vendor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbwbbxs0mz7n6jxeso9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbwbbxs0mz7n6jxeso9j.png" alt="Image description" width="633" height="840"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Handle YouTube Parameters
&lt;/h3&gt;

&lt;p&gt;Add this to a custom &lt;code&gt;.module&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * @file
 * Helper module for Media oEmbed YouTube player parameters.
 *  
 * @see https://www.drupal.org/project/2788249/issues/3266590
 */&lt;/span&gt; 

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Drupal\Component\Utility\UrlHelper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Drupal\media\IFrameMarkup&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Implements hook_preprocess_HOOK().
 */&lt;/span&gt; 
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;HOOK_preprocess_media_oembed_iframe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$variables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;\Drupal&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;$params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UrlHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;http_build_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nv"&gt;$original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$variables&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"media"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;__toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'feature=oembed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'feature=oembed&amp;amp;'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nv"&gt;$variables&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"media"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IFrameMarkup&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This produced a clean implementation of remote video for full-width, YouTube videos with parameters. This has not been tested on Vimeo or other providers. I hope you've found this helpful.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>learning</category>
      <category>career</category>
    </item>
    <item>
      <title>Vuex Airbnb JS ESLint</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Mon, 04 Apr 2022 19:27:12 +0000</pubDate>
      <link>https://dev.to/jcandan/vue-airbnb-js-eslint-74e</link>
      <guid>https://dev.to/jcandan/vue-airbnb-js-eslint-74e</guid>
      <description>&lt;p&gt;I found the following useful when working with VueJS and using the Airbnb ESLint rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .eslintrc.yml

rules:
  # Airbnb Eslint sets the no-param-reassign props option to true, which warns
  # against the modification of parameter properties. However, in order to
  # control the state (using Vuex), one must use mutations/actions.
  # Set it to false.
  'no-param-reassign':
    - error
    -
      props: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>reCAPTCHA + Laravel + Vue</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Mon, 13 Dec 2021 19:10:22 +0000</pubDate>
      <link>https://dev.to/jcandan/recaptcha-laravel-vue-ckc</link>
      <guid>https://dev.to/jcandan/recaptcha-laravel-vue-ckc</guid>
      <description>&lt;p&gt;We'll implement a reCAPTCHA Vue package in the frontend and a PHP package for the backend. We'll ensure each step is working as expected along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;1. Provide reCAPTCHA keys&lt;/li&gt;
&lt;li&gt;2. Prepare the front-end&lt;/li&gt;
&lt;li&gt;3. Error Handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Assumes you have a working Laravel 8 and Vue 2.0 project, Composer and NPM, and a Vue form to which you want to add reCAPTCHA.&lt;/p&gt;

&lt;p&gt;This was built onto a project that uses InertiaJS. However, I believe this &lt;em&gt;should&lt;/em&gt; work on a separated front-end and back-end. As such, each sub-section is prefixed with either &lt;strong&gt;(Laravel)&lt;/strong&gt; or &lt;strong&gt;(Vue)&lt;/strong&gt; to indicate to which side the changes belong.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Provide reCAPTCHA keys &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We'll need a valid SITEKEY and SECRET from Google.&lt;/p&gt;

&lt;h3&gt;
  
  
  (Laravel) Store environment variables
&lt;/h3&gt;

&lt;p&gt;Add keys to your &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Do not commit your &lt;code&gt;.env&lt;/code&gt; file. You should commit a &lt;code&gt;.env.example&lt;/code&gt; with secure values redacted.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RECAPTCHAV2_SITEKEY=&amp;lt;yoursitekeyhere&amp;gt;
RECAPTCHAV2_SECRET=&amp;lt;yoursecrethere&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; Do not expose &lt;code&gt;RECAPTCHAV2_SECRET&lt;/code&gt; to the front-end.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If using VueCLI&lt;/em&gt;, environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files. &lt;em&gt;If using VueCLI&lt;/em&gt;, &lt;strong&gt;Do not&lt;/strong&gt; store this value in &lt;em&gt;any&lt;/em&gt; &lt;code&gt;.env&lt;/code&gt; file on Production, not even &lt;code&gt;.env.production&lt;/code&gt;. They are auto-loaded by VueCLI. It is okay to expose the &lt;code&gt;SITEKEY&lt;/code&gt;, but for the SECRET, use some other secure method in Production, such as setting environment variables without this &lt;code&gt;dotenv&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Define these environment variables in Laravel's configuration.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;config/recaptchav2.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'origin'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'RECAPTCHAV2_ORIGIN'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://www.google.com/recaptcha'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'sitekey'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'RECAPTCHAV2_SITEKEY'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'secret'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'RECAPTCHAV2_SECRET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (Laravel) Share environment variable with front-end
&lt;/h3&gt;

&lt;p&gt;Here's that InertiaJS piece mentioned in the prerequisites above. &lt;/p&gt;

&lt;p&gt;The gist of this change is that we want to share the &lt;code&gt;RECAPTCHAV2_SITEKEY&lt;/code&gt; environment variable with the front-end. &lt;/p&gt;

&lt;p&gt;If not using InertiaJS, you should be able to provide the environment variable to Vue some other way (such as mentioned above if using VueCLI). &lt;/p&gt;

&lt;p&gt;Here's an InertiaJS way of doing it:&lt;/p&gt;

&lt;p&gt;We do this with InertiaJS middleware in &lt;code&gt;app/Http/Middleware/HandleInertiaRequests.php&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; public function share(Request $request)
 {
     return array_merge(parent::share($request), [
&lt;span class="gi"&gt;+        // Provide the reCAPTCHA site key to the front-end.
+        'recaptchav2_sitekey' =&amp;gt; config('recaptchav2.sitekey'),
+        // DO NOT SHARE RECAPTCHAV2_SECRET.
&lt;/span&gt;     ]);
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  (Vue) Ensure successful share to front-end
&lt;/h4&gt;

&lt;p&gt;In your Vue form somewhere, we'll temporarily plop in the following to ensure the key is being passed successfully from the backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; &amp;lt;template&amp;gt;
&lt;span class="gi"&gt;+  {{ $page.props.recaptchav2_sitekey }}
&lt;/span&gt;   ...
 &amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This may be different depending on the route taken to expose the environment variable. With VueCLI it would be &lt;code&gt;{{ process.env.RECAPTCHAV2_SITEKEY }}&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Browsing the page should display your site key.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Prepare the front-end &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We have a securely stored secret key, and can display the site key on the page. Now, let's get a working reCAPTCHA to appear on the page. &lt;/p&gt;

&lt;h3&gt;
  
  
  (Vue) Add reCAPTCHA Vue
&lt;/h3&gt;

&lt;p&gt;Require the reCAPTCHA Vue package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save @vue/composition-api vue-recaptcha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the reCAPTCHA to your component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; &amp;lt;template&amp;gt;
&lt;span class="gd"&gt;-  {{ $page.props.recaptchav2_sitekey }}
&lt;/span&gt;   &amp;lt;form&amp;gt;
     ...
&lt;span class="gi"&gt;+    &amp;lt;vue-recaptcha 
+      :sitekey="$page.props.recaptchav2_sitekey" 
+    /&amp;gt;
&lt;/span&gt;   &amp;lt;/form&amp;gt;
 &amp;lt;/template&amp;gt;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+&amp;lt;script&amp;gt;
+import { VueRecaptcha } from 'vue-recaptcha';
+
+export default {
+  components: {
+    VueRecaptcha,
+  },
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you should have a visible, working reCAPTCHA on your page.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Prepare the back-end
&lt;/h2&gt;

&lt;h3&gt;
  
  
  (Laravel) Add middleware
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require google/recaptcha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define a reCAPTCHA middleware class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * @file app/Http/Middleware/Recaptcha.php
 */&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Middleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Closure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ReCaptcha\ReCaptcha&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;GoogleRecaptcha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Recaptcha&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Closure&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleRecaptcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'recaptchav2.secret'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'g-recaptcha-response'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;back&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Recaptcha failed. Please try again.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List this new middleware in &lt;code&gt;/app/Http/Kernel.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; 'password.confirm' =&amp;gt; \Illuminate\Auth\Middleware\RequirePassword::class,
&lt;span class="gi"&gt;+'recaptcha' =&amp;gt; \App\Http\Middleware\Recaptcha::class,
&lt;/span&gt; 'signed' =&amp;gt; \Illuminate\Routing\Middleware\ValidateSignature::class,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, attach this middleware to your form's submit route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; Route::post('/my-form-action', [
     MyFormController::class, 
     'submitForm'
&lt;span class="gd"&gt;-]);
&lt;/span&gt;&lt;span class="gi"&gt;+])
+    -&amp;gt;middleware('recaptcha');
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (Vue) Pass the reCAPTCHA response
&lt;/h3&gt;

&lt;p&gt;The reCAPTCHA backend expects a token response from the front-end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-    &amp;lt;vue-recaptcha 
-      :sitekey="$page.props.recaptchav2_sitekey" 
&lt;/span&gt;&lt;span class="gi"&gt;+      @verify="onCaptchaVerify"
&lt;/span&gt;&lt;span class="gd"&gt;-    /&amp;gt;
&lt;/span&gt; ...
 methods: {
&lt;span class="gi"&gt;+  onCaptchaVerify(token) {
+    // Provide the token response to the form object.
+    this.form['g-recaptcha-response'] = token;
&lt;/span&gt;   },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: This assumes you are using a form data object.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point, you can verify you are human and submit the form. If you fail to check the CAPTCHA box, submitting the form should redirect you back with a &lt;code&gt;Recaptcha failed. Please try again.&lt;/code&gt; status.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Error Handling &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;On submit, if the reCAPTCHA has failed or has not been attempted, we want to indicate that to the visitor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favk945u0ja4mtm02rq56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favk945u0ja4mtm02rq56.png" alt="Image description" width="327" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make the following additions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; &amp;lt;vue-recaptcha
   :sitekey="$page.props.recaptchav2_sitekey"
   @verify="onCaptchaVerify"
 /&amp;gt;
&lt;span class="gi"&gt;+&amp;lt;span
+  v-if="recaptcha_error"
+  class="error-message"
+&amp;gt;
+  Please confirm you are not a robot.
+&amp;lt;/span&amp;gt;
&lt;/span&gt; ...
   data() {
     return {
&lt;span class="gi"&gt;+      recaptcha_error: false,
&lt;/span&gt;       form: {
         ...
       }
     }
   },
   methods: {
     onSubmit() {
&lt;span class="gi"&gt;+      if (!this.form['g-recaptcha-response']) {
+        // Show error after submit.
+        this.recaptcha_error = true;
+      } else {
+        // Proceed with submission.
+      }
&lt;/span&gt;     }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enjoy your functioning reCAPTCHA.&lt;/p&gt;

</description>
      <category>captcha</category>
      <category>vue</category>
      <category>laravel</category>
      <category>inertiajs</category>
    </item>
    <item>
      <title>Lando + WSL2 via Hyperdrive</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Fri, 27 Aug 2021 15:48:05 +0000</pubDate>
      <link>https://dev.to/jcandan/lando-wsl2-via-hyperdrive-3ecm</link>
      <guid>https://dev.to/jcandan/lando-wsl2-via-hyperdrive-3ecm</guid>
      <description>&lt;h3&gt;
  
  
  UPDATE 7/8/2024
&lt;/h3&gt;

&lt;p&gt;Lando has released v3.21.0! This includes a backport of Lando 4 installation process and plugin handling. Hyperdrive--Lando's previous install script helper--is no longer needed.&lt;/p&gt;

&lt;p&gt;It also seems Lando has removed the "Setup Lando on Windows with WSL2" article. So, you'll have to rely on Microsoft's own &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install" rel="noopener noreferrer"&gt;How to install Linux on Windows with WSL&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Only recently, WSL2 was made default, run &lt;code&gt;wsl -l -v&lt;/code&gt; to ensure you are running WSL2. If not, you need to follow &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install#upgrade-version-from-wsl-1-to-wsl-2" rel="noopener noreferrer"&gt;Upgrade version from WSL 1 to WSL 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All you need to do is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get WSL2 (see above).&lt;/li&gt;
&lt;li&gt;Open the Windows Store and get the latest Ubuntu (e.g. 22.04).&lt;/li&gt;
&lt;li&gt;Follow the Linux link within Lando's &lt;a href="https://docs.lando.dev/install/windows.html#installation-in-a-wsl2-linux-environment" rel="noopener noreferrer"&gt;Installation in a WSL2 Linux Environment&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the final update this article will receive. I hope it was helpful!&lt;/p&gt;

&lt;h3&gt;
  
  
  UPDATE 9/15/2023
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hyperdrive supported up to Ubuntu 18.04. &lt;/li&gt;
&lt;li&gt;Docker Engine supports Ubuntu 20.04+.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suggestions to get Lando on Windows via WSL2:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get WSL2. Typically WSL1 is default, you need to be sure to follow the Windows docs to get WSL2.&lt;/li&gt;
&lt;li&gt;Get Ubuntu 20.04 or 22.04 via the Windows Store.&lt;/li&gt;
&lt;li&gt;Follow Docker's &lt;a href="https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository" rel="noopener noreferrer"&gt;Install using the Apt repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow the Then, Get The Latest Lando section below.&lt;/li&gt;
&lt;li&gt;You may additionally wish to update curl and git, and configure your git user and SSH keys.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  UPDATE 6/7/2022
&lt;/h3&gt;

&lt;p&gt;Updated the command lines to be copy/paste-ready for Ubuntu terminal in Windows. I noticed that it had trouble with the multi-line commands broken up by the back-slash (\) character.&lt;/p&gt;

&lt;p&gt;Also, added a section to handle Docker version updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Falling short
&lt;/h4&gt;

&lt;p&gt;If you've recently followed the awesome instructions to &lt;a href="https://docs.lando.dev/guides/setup-lando-on-windows-with-wsl-2.html" rel="noopener noreferrer"&gt;Setup Lando on Windows with WSL2&lt;/a&gt;, then you may have noticed your version of Lando is quite behind, or may not have completely worked at all.&lt;/p&gt;

&lt;p&gt;Hyperdrive hasn’t seen a lot of love, so while it’s super awesome, it’s not up-to-date. They’re about to revamp it to be even more awesome, but until then, we need to jump through a couple hoops to install the latest stable release of Lando.&lt;/p&gt;

&lt;p&gt;While Hyperdrive is being revamped, we need to use the last stable version, &lt;code&gt;v0.6.1&lt;/code&gt;. However, even that hadn't received a relatively recent change to the stable release link.&lt;/p&gt;

&lt;p&gt;Here’s what you need to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  First, Run Hyperdrive
&lt;/h3&gt;

&lt;p&gt;If you've already run Hyperdrive, you likely won't need this step.&lt;/p&gt;

&lt;p&gt;If it failed to complete, you may have missed the instruction to &lt;code&gt;sudo apt --fix-broken install&lt;/code&gt; without any specified package. Once that's done, run it again. You'll find a working Hyperdrive install command below.&lt;/p&gt;

&lt;p&gt;Follow the documentation if you want to change the customizations included below, but this will work for most folks. Pop a &lt;code&gt;--vim&lt;/code&gt; flag on there too if you wish. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IMPORTANT!&lt;/p&gt;

&lt;p&gt;Don't forget to change your name and email address. This is used to populate Git config.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -Ls https://github.com/lando/hyperdrive/releases/download/v0.6.1/hyperdrive &amp;gt; /tmp/hyperdrive; chmod +x /tmp/hyperdrive; /tmp/hyperdrive --name "YOUR NAME HERE" --email your.email@thisismyawesomedomainnameandyoucanthave.one -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Docker
&lt;/h3&gt;

&lt;p&gt;It doesn't look like Hyperdrive grabs the latest Docker version. You may want to check if Lando supports the latest Docker, then use the following 3 commands to remove Docker and re-install the latest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get remove docker docker-engine docker.io containerd runc -y; sudo apt-get update -y; sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="https://docs.docker.com/engine/install/ubuntu/" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/install/ubuntu/&lt;/a&gt; for resources on specifying Docker version if the latest is not yet supported by Lando.&lt;/p&gt;

&lt;h3&gt;
  
  
  Then, Get The Latest Lando
&lt;/h3&gt;

&lt;p&gt;Head over to &lt;a href="https://github.com/lando/lando/releases" rel="noopener noreferrer"&gt;Lando Releases&lt;/a&gt; and make a note of the version from the &lt;strong&gt;latest&lt;/strong&gt; stable release.&lt;/p&gt;

&lt;p&gt;Copy/paste the command below &lt;strong&gt;into a text editor&lt;/strong&gt;. Be sure to &lt;strong&gt;replace&lt;/strong&gt; the Github releases link with the one from the releases page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -f#SL -o /tmp/lando.deb https://github.com/lando/lando/releases/download/v3.18.0/lando-x64-v3.18.0.deb; sudo dpkg -i --ignore-depends=docker-ce /tmp/lando.deb; rm -f /tmp/lando.deb;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have made the edit to the command line above, run it.&lt;/p&gt;

&lt;p&gt;That does it. Run &lt;code&gt;lando version&lt;/code&gt; to see you are on the latest. Cheers!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Install Terminus Plugins In Lando</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Mon, 18 May 2020 18:12:37 +0000</pubDate>
      <link>https://dev.to/jcandan/install-terminus-plugins-in-lando-142a</link>
      <guid>https://dev.to/jcandan/install-terminus-plugins-in-lando-142a</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;When you use Lando with Pantheon, and you want to install a Terminus plugin to your Lando local development environment, you'll want to go with something like the following.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  appserver:
    build:
      - /bin/sh -c "[ -d /var/www/.terminus/plugins ] || mkdir -p /var/www/.terminus/plugins"
      - /bin/sh -c "[ -d /var/www/.terminus/plugins/terminus-secrets-plugin ] || composer create-project -d /var/www/.terminus/plugins pantheon-systems/terminus-secrets-plugin:~1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why this way?
&lt;/h3&gt;

&lt;p&gt;This avoids an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Creating a "pantheon-systems/terminus-secrets-plugin:~1" project at "./terminus-build-tools-plugin"


  [InvalidArgumentException]                                                                
  Project directory "/var/www/.terminus/plugins/terminus-secrets-plugin" is not empty.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that it is trying to override already existing directory and files.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Cron with Lando</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Thu, 27 Feb 2020 12:43:29 +0000</pubDate>
      <link>https://dev.to/jcandan/cron-with-lando-4lnh</link>
      <guid>https://dev.to/jcandan/cron-with-lando-4lnh</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update Feb 28, 2020:&lt;/strong&gt; It turns out that cron runs within it's own limited environment. See below for more details.&lt;/p&gt;

&lt;p&gt;In Laravel, we want the following cron configuration to fire the framework's scheduler. Place this in a file somewhere within your project code base. I went with &lt;code&gt;resources/config/cron.txt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * * php /app/artisan schedule:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The cron daemon was designed in such a way that it does NOT execute commands within your normal shell environment. That means your $PATH will not match your container's, and your php.ini memory limit may not be set. That said, we need to supply the full path from within the Lando container to &lt;code&gt;php&lt;/code&gt;. Typically, this will be &lt;code&gt;/usr/local/bin/php&lt;/code&gt;. In that case, use the following:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * * /usr/local/bin/php -d memory_limit=-1 /app/artisan schedule:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to get cron installed. You'll want to perform this as root during build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    build_as_root:
      - apt-get update -y
      - apt-get install cron -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we're ready to fire the cron service. Because cron services all users in a system, it must be started with root priviliges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    run_as_root:
      - service cron start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are, born to be kings; we're the princes of the the universe.&lt;/p&gt;

&lt;p&gt;Oh, sorry, off on a tangent. Okay, we can now store our cron config with crontab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    run:
      - crontab /app/resources/config/cron.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put this altogether, and you will have arrived.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: my-project
recipe: laravel
config:
  webroot: public
services:
  appserver:
    build_as_root:
      - apt-get update -y
      - apt-get install cron -y
    run_as_root:
      - service cron start
    run:
      - crontab /app/resources/config/cron.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that things have gone as planned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ lando ssh
www-data@ba70770a45a1:/app$ service cron status
[ ok ] cron is running.
www-data@ba70770a45a1:/app$ crontab -l
* * * * * php /app/artisan schedule:run
www-data@ba70770a45a1:/app$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enjoy.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>lando</category>
      <category>cron</category>
    </item>
    <item>
      <title>Lando and Flask</title>
      <dc:creator>James Candan</dc:creator>
      <pubDate>Wed, 12 Feb 2020 14:14:47 +0000</pubDate>
      <link>https://dev.to/jcandan/lando-and-flask-556j</link>
      <guid>https://dev.to/jcandan/lando-and-flask-556j</guid>
      <description>&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;You'll need Lando installed, and that's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Lando
&lt;/h2&gt;

&lt;p&gt;Get into your project directory, and get things started with a Lando file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my-project
touch .lando.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name your Lando project and define a python service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-example&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python:3.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expose &lt;code&gt;python&lt;/code&gt; and &lt;code&gt;pip&lt;/code&gt; command line tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Flask
&lt;/h2&gt;

&lt;p&gt;Fire up the container, and let's get the requirements going. From the command line, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lando start
lando pip install Flask
lando pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It may be the case that this will add carriage return characters to your &lt;code&gt;requirements.txt&lt;/code&gt; file. In that case, you may have to run &lt;code&gt;lando ssh -s python -c 'pip freeze &amp;gt; requirements.txt'&lt;/code&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now tell lando that we want it to install requirements during build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python:3.5&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-r&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app/requirements.txt'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build an app
&lt;/h2&gt;

&lt;p&gt;Build your &lt;code&gt;app.py&lt;/code&gt; file, specifying the host as &lt;code&gt;0.0.0.0&lt;/code&gt;, with no port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flask defaults to port 5000, so let's set up our Lando proxy with that port exposed internally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;flask-example.lndo.site:5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tell lando to run the python app at startup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python:3.5&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-r&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app/requirements.txt'&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;python /app/app.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Your Lando file will finally look like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-example&lt;/span&gt;
&lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;flask-example.lndo.site:5000&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python:3.7&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-r&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app/requirements.txt'&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;python /app/app.py&lt;/span&gt;
&lt;span class="na"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>lando</category>
      <category>python</category>
      <category>flask</category>
    </item>
  </channel>
</rss>
