<?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: George Bougakov</title>
    <description>The latest articles on DEV Community by George Bougakov (@gb).</description>
    <link>https://dev.to/gb</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%2F177751%2Ffed4d63b-a753-4713-9f06-7addf0e6f983.jpeg</url>
      <title>DEV Community: George Bougakov</title>
      <link>https://dev.to/gb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gb"/>
    <language>en</language>
    <item>
      <title>Seven Deadly Slack Sins (And How to Solve Them with Automation)</title>
      <dc:creator>George Bougakov</dc:creator>
      <pubDate>Tue, 07 Jul 2020 23:02:12 +0000</pubDate>
      <link>https://dev.to/gb/seven-deadly-slack-sins-and-how-to-solve-them-with-automation-1op3</link>
      <guid>https://dev.to/gb/seven-deadly-slack-sins-and-how-to-solve-them-with-automation-1op3</guid>
      <description>&lt;p&gt;&lt;em&gt;All names are fictional and any similarities to any person, living or dead, are purely coincidental, profile pictures are from Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can read the original version &lt;a href="https://blog.gbougakov.dev/posts/slack-sins"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Looks like some offices will be staying remote until the end of the summer, &lt;a href="https://twitter.com/tobi/status/1263483496087064579?s=21"&gt;or even permanently&lt;/a&gt;. That means that for some, Slack will become the center of all business processes and communications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_47Gxbhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://storage.yandexcloud.net/gb-assets-hot/blog-assets/slack-sins/main.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_47Gxbhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://storage.yandexcloud.net/gb-assets-hot/blog-assets/slack-sins/main.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We at Skyeng started building a remote team long before COVID-19 happened and probably ran into most of the issues of communicating remotely with colleagues and realized that we could solve most of them with bots, so we did!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sin 1. Asking dumb stuff and posting memes in #general
&lt;/h2&gt;

&lt;p&gt;Have you ever accidentally hit “Reply All” on a company announcement sent to you and hundreds of your coworkers? If you did, that was probably a very fun and unforgettable experience :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K8C6aDPA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fl20h1fsplm1w2kbr0m0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K8C6aDPA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fl20h1fsplm1w2kbr0m0.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Slack there’s a better version of this sin - post something irrelevant to most people in #general. Bonus points for tagging @channel.&lt;/p&gt;

&lt;p&gt;And here you are, sitting peacefully, working away and hear a notification chime... “Surely, that’s something important” — you think, because you fine-tuned your notifications so that you get them only when someone DMs or mentions you. And then you see a completely irrelevant notification, get mad and put an angry emoji under the message.&lt;/p&gt;

&lt;p&gt;We made a list of people that we trust to make relevant announcements, and for others we applied these moderation rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you attempt to post in #general, our bot deletes the post instantly, so that people don’t get a notification&lt;/li&gt;
&lt;li&gt;Our bot reminds what is the purpose of #general&lt;/li&gt;
&lt;li&gt;If the author still thinks that their message is relevant, they can click a button and the message will be sent to a private channel for moderation&lt;/li&gt;
&lt;li&gt;After that, a moderator from the internal communications team will review the message and either approve it or explain where is the best place for the message to be posted&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sin 2. Not reading the pinned message
&lt;/h2&gt;

&lt;p&gt;Cool, we’re done with #general! But there are still lots of channels with similar names. We, for example, have dozens of channels for each project with a prefix (usually the name of the project or the Jira project key) and a suffix (usually the name of the subteam)&lt;/p&gt;

&lt;p&gt;Here’s an example - you found a bug in the mobile app and want to report it, so you hit Cmd+K and type in #mobile. Here’s what you see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ntPt1Zh4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://storage.yandexcloud.net/gb-assets-hot/blog-assets/slack-sins/mobile-channels.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ntPt1Zh4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://storage.yandexcloud.net/gb-assets-hot/blog-assets/slack-sins/mobile-channels.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More channels! (P.S. We now have a bot that automatically archives channels if they’re left dormant for more than 90 days)&lt;/p&gt;

&lt;p&gt;Trust us - if you have a lot of similarly named channels, people will get lost and ask questions in wrong places.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mWHudb5Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sfll19hy43zmsg67xwxa.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mWHudb5Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sfll19hy43zmsg67xwxa.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before, we put a guide where to ask which question in the pinned message. Nobody reads it. Even the people who put stuff in the pinned message. And again, we solved this problem with a bot!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You add it to a channel&lt;/li&gt;
&lt;li&gt;When someone joins a channel, the bot sends an ephemeral (“Only you can see this message”) message with all the relevant information&lt;/li&gt;
&lt;li&gt;It only helps sometimes, but sometimes is better than never… I guess :)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sin 3. Asking questions that were already answered
&lt;/h2&gt;

&lt;p&gt;We actually have a whole army of bots dedicated to solving this mess. Everything began with teachers - they, as contractors doing work for Skyeng, are granted limited access to our Slack so that they can talk directly with our support team. They even have a very detailed and always up-to-date wiki. It even has a special page where we explain how to handle “emergencies”, for example, when the video call cuts out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vett1hd0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gyo783kp7acm58bnk01y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vett1hd0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gyo783kp7acm58bnk01y.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When an emergency happens, teachers panic. When teachers panic, they forget stuff and ask questions in their support channels.&lt;/p&gt;

&lt;p&gt;We thought of a simple solution: integrate our wiki with Slack. When someone asks a question in a support channel, our bot takes the text, deletes “hellos” and “pleases” and puts it into the wiki search. After that, it just sends the top 5 articles and 90% of the time one of them answers the question&lt;/p&gt;

&lt;h2&gt;
  
  
  Sin 4. Forgetting to move tasks to task trackers
&lt;/h2&gt;

&lt;p&gt;At Skyeng, we have a channel where our infrastructure team can help you out with all of your IT questions. Most of the questions can be answered right then and there, but some require some work. And let’s be honest — unless you move that ticket to Jira, you will forget about it in about two hours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8aJ6r2D2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bsn5as9b5hb323gpjfig.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8aJ6r2D2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bsn5as9b5hb323gpjfig.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have a bot that automatically creates a ticket for every single message in support channels, then the support team can use reactions or the Jira UI to move tickets to other statuses or close them. Also, we automatically match the sender to their Jira profile and mark them as a reporter on the ticket, so that they can track it in Jira&lt;/p&gt;

&lt;p&gt;We even have a bot that… supervises this bot (I know, that’s confusing, but hang in there) - it counts messages, who answered them and asks people to “rate the service”. All this data is collected in our data warehouse and is being used to continuously improve the support experience (that just sounded like a privacy policy, sorry)&lt;/p&gt;

&lt;h2&gt;
  
  
  Sin 5. Spending unjustified amounts of time gathering and posting data from other systems
&lt;/h2&gt;

&lt;p&gt;Every development team leader at Skyeng has an arsenal of bots that save them time (and money for the company). Here are some of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Burndown delivers daily sprint burndown charts to motivate developers&lt;/li&gt;
&lt;li&gt;Arseny gathers data from Jira, reminds about pending code reviews and deploys and reminds people to log their time&lt;/li&gt;
&lt;li&gt;Jake saves team leaders an hour a day by simplifying the process of selecting tasks for the next sprint. It automatically gathers all tickets with a specific status and sends a poll to the team channel. Then, team members vote on tickets they would like to discuss and Jake generates a plan for the team meeting so that the time is not wasted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oh, and our email support team uses a bot that brings emails into Slack, so that our agents can easily consult with their leaders on specific cases and forward all relevant information to the designated teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sin 6. Not making sure that urgent messages reach their recipient
&lt;/h2&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/436253009" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This bot can wake up our CTO&lt;/p&gt;

&lt;p&gt;Stuff happens. Servers go down. Even at night. For emergencies and major outages we have a designated channel. We also use OpsGenie to automatically alert our DevOps team about any outages by paging calling them on their mobile phone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the on-call engineer doesn’t acknowledge the message within 30 seconds, our bot calls them via OpsGenie and tells them that everything is bad and asks them to press 1 if they acknowledged the alert.&lt;/li&gt;
&lt;li&gt;If the on-call engineer doesn’t pick up or picks up and doesn’t press 1, the alert is immediately escalated to their team leader&lt;/li&gt;
&lt;li&gt;If the team leader doesn’t pick up, rinse and repeat until you reach the CTO&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sin 7. Making typos
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a1fOrUSq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d8i9geijsvocbx2737q1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a1fOrUSq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d8i9geijsvocbx2737q1.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When all communication in the company is text-based, you start to understand why you had to take that English class. Slackbot has a built-in function when it watches for keywords in messages and replies to them with a custom text message. With one Typeform and two hours we turned Slackbot into a Grammarnazi, but after a month people started asking us to disable it. It was fun while it lasted :)&lt;/p&gt;

&lt;p&gt;P.S. And this is far from over. We have dozens of bots doing different things in our Slack. For example, we recently built one that turns links from annoying screenshot services into simple attachments&lt;/p&gt;

</description>
      <category>slack</category>
      <category>node</category>
      <category>javascript</category>
      <category>bots</category>
    </item>
    <item>
      <title>Coding on the iPad, iPadOS 13.4 edition</title>
      <dc:creator>George Bougakov</dc:creator>
      <pubDate>Wed, 08 Apr 2020 14:50:50 +0000</pubDate>
      <link>https://dev.to/gb/coding-on-the-ipad-ipados-13-4-edition-3k0c</link>
      <guid>https://dev.to/gb/coding-on-the-ipad-ipados-13-4-edition-3k0c</guid>
      <description>&lt;p&gt;Not that long ago Apple introduced trackpad and mouse support in iPadOS 13.4, so I decided to connect my Magic Mouse to my iPad Pro 11" (2018) and even though some apps didn't include real trackpad support yet, it worked like a charm! Even the hover and drag events worked in Safari!.&lt;/p&gt;

&lt;p&gt;I decided to try running VS Code on the iPad, and with a mouse it worked almost flawlessly!&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Qkn7o_2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1241024548251881473/pu/img/4riWB1p5DiNDXF3o.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--HdTbpvxY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1211971845739728896/NQjLfWNK_normal.jpg" alt="George B. profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        George B.
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @gbougakov
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      After Apple introduced mouse/trackpad support on the iPad, I decided to try out Visual Studio Code on it and it works flawlessly (debugger too)! &lt;br&gt;&lt;br&gt;cc &lt;a href="https://twitter.com/viticci"&gt;@viticci&lt;/a&gt; &lt;a href="https://twitter.com/stroughtonsmith"&gt;@stroughtonsmith&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      15:31 PM - 20 Mar 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1241024611204001794" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1241024611204001794" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1241024611204001794" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Quite a few people asked me how I did that and the answer is code-server.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/coder"&gt;
        coder
      &lt;/a&gt; / &lt;a href="https://github.com/coder/code-server"&gt;
        code-server
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      VS Code in the browser
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
code-server&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/coder/code-server/discussions"&gt;&lt;img src="https://camo.githubusercontent.com/d226573a5a15024ca4fed6a7fc389f4bb310c2258050508ead1c34a0ac29b1be/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532304769744875622d25323044697363757373696f6e732d677261792e7376673f6c6f6e6743616368653d74727565266c6f676f3d67697468756226636f6c6f72423d707572706c65" alt='"GitHub Discussions"'&gt;&lt;/a&gt; &lt;a href="https://coder.com/community" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/6f603da6663957ad0f2c3f81e1c1ea3eb1b3eb1161b04c297aa12615db92cc11/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6a6f696e2d75732532306f6e253230736c61636b2d677261792e7376673f6c6f6e6743616368653d74727565266c6f676f3d736c61636b26636f6c6f72423d627269676874677265656e" alt='"Join us on Slack"'&gt;&lt;/a&gt; &lt;a href="https://twitter.com/coderhq" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/0631514174426e6e816bb06b8aeef112b257054d909d9bc8dcc76e56c8b739b0/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f436f64657248513f6c6162656c3d253430436f6465724851267374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt; &lt;a href="https://codecov.io/gh/coder/code-server" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/c19f0c18caa50c0bd387433b0ea0d4e9c55f117b707bc1b138c25b458d84727f/68747470733a2f2f636f6465636f762e696f2f67682f636f6465722f636f64652d7365727665722f6272616e63682f6d61696e2f67726170682f62616467652e7376673f746f6b656e3d35694d396661726a6e43" alt="codecov"&gt;&lt;/a&gt; &lt;a href="https://coder.com/docs/code-server/latest" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/b247f7c4d10a9c813231d106273b56e394494ca182def882c8baa2798f582ae7/68747470733a2f2f696d672e736869656c64732e696f2f7374617469632f76313f6c6162656c3d446f6373266d6573736167653d7365652532306c617465737426636f6c6f723d626c7565" alt="See latest"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Run &lt;a href="https://github.com/Microsoft/vscode"&gt;VS Code&lt;/a&gt; on any machine anywhere and
access it in the browser.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/coder/code-server./assets/screenshot.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kPA2_B4n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/coder/code-server./assets/screenshot.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Highlights&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Code on any device with a consistent development environment&lt;/li&gt;
&lt;li&gt;Use cloud servers to speed up tests, compilations, downloads, and more&lt;/li&gt;
&lt;li&gt;Preserve battery life when you're on the go; all intensive tasks run on your
server&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Requirements&lt;/h2&gt;
&lt;p&gt;See &lt;a href="https://github.com/coder/code-serverrequirements.md"&gt;requirements&lt;/a&gt; for minimum specs, as well as instructions
on how to set up a Google VM on which you can install code-server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs&lt;/p&gt;
&lt;h2&gt;
Getting started&lt;/h2&gt;
&lt;p&gt;There are four ways to get started:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using the &lt;a href="https://github.com/coder/code-server/blob/main/install.sh"&gt;install
script&lt;/a&gt;, which
automates most of the process. The script uses the system package manager if
possible.&lt;/li&gt;
&lt;li&gt;Manually &lt;a href="https://coder.com/docs/code-server/latest/install" rel="nofollow"&gt;installing
code-server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Deploy code-server to your team with &lt;a href="https://cdr.co/coder-github" rel="nofollow"&gt;coder/coder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Using our one-click buttons and guides to &lt;a href="https://github.com/coder/deploy-code-server"&gt;deploy code-server to a cloud
provider&lt;/a&gt; ⚡
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you use the install script, you can preview what occurs…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/coder/code-server"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It works by running the language server (debugger and IntelliSense), extensions and the file system part in the cloud on a VPS, and rendering the UI in your browser. It is able to do that because VS Code is actually written using web technologies and packaged with Electron.&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's set it up
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Step one. Get a server
&lt;/h2&gt;

&lt;p&gt;It can be a Mac Mini in your attic, a rented server from AWS or anything that runs Linux or macOS, some people have even &lt;a href="https://www.youtube.com/watch?v=IR6sDcKo3V8"&gt;tried&lt;/a&gt; using a Raspberry Pi with an iPad and it works like a charm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step two. Install code-server
&lt;/h2&gt;

&lt;p&gt;Download the &lt;a href="https://github.com/cdr/code-server/releases/latest"&gt;latest prebuilt binary&lt;/a&gt; from the GitHub Releases to your server. Untar/unzip it somewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step three. Run code-server
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into the code-server directory. There will be an executable file called &lt;code&gt;code-server&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Variant A. If you don't want to set up SSH forwarding (faster, more convenient, requires a registered domain, less secure)
&lt;/h3&gt;

&lt;p&gt;First of all, get an SSL certificate&lt;br&gt;
You can get one for free from Let's Encrypt using &lt;a href="https://github.com/acmesh-official/acme.sh#1-how-to-install"&gt;acme.sh&lt;/a&gt;. Their README is pretty easy to follow, so I won't get into much detail.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/acmesh-official"&gt;
        acmesh-official
      &lt;/a&gt; / &lt;a href="https://github.com/acmesh-official/acme.sh"&gt;
        acme.sh
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A pure Unix shell script implementing ACME client protocol
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Then, you can run code-server with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"correct-horse-battery-staple"&lt;/span&gt; ./code-server 
    &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;PORT] 
    &lt;span class="nt"&gt;--cert&lt;/span&gt; ~/.acme.sh/[DOMAIN]/[DOMAIN].cer 
    &lt;span class="nt"&gt;--cert-key&lt;/span&gt; ~/.acme.sh/[DOMAIN]/[DOMAIN].key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voila! You can now open your browser, enter the password you set in the environment variable and code&lt;/p&gt;

&lt;h3&gt;
  
  
  Variant B. Set up SSH forwarding (requires an SSH client, but is easier and more secure)
&lt;/h3&gt;

&lt;p&gt;In your SSH client, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;PORT]:localhost:[PORT] root@[YOUR SERVER]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An SSH session will open, where you can start code-server with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./code-server 
    &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;PORT]
    &lt;span class="nt"&gt;--auth&lt;/span&gt; none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, open &lt;code&gt;http://localhost:[PORT]&lt;/code&gt; in your browser and code!&lt;/p&gt;

&lt;h1&gt;
  
  
  But how well does it work on the iPad?
&lt;/h1&gt;

&lt;p&gt;If you have a keyboard and a mouse, the experience is flawless... almost. Here are a few quirks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Custom fonts installed via iFont don’t work in Safari (fixed by loading them via CSS)&lt;/li&gt;
&lt;li&gt;Scrolling wheel doesn’t work in editor (arrow keys and scrollbar to the rescue)&lt;/li&gt;
&lt;li&gt;Lack of escape key (ctrl+[ works, or you can remap ESC and Caps Lock in iPadOS Settings)&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Do you actually use it?
&lt;/h1&gt;

&lt;p&gt;Yeah! I am a backend developer by day, and it's great coding on an iPad. Frontenders will disagree because iPad Safari lacks devtools, but let's hope that will change in iPadOS 14 :)&lt;/p&gt;

&lt;p&gt;This is my first article on dev.to and I'd love it if you share your feedback in the comments! Also, feel free to ask any questions :)&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>ipad</category>
      <category>cloud</category>
      <category>setup</category>
    </item>
  </channel>
</rss>
