<?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: Coda</title>
    <description>The latest articles on DEV Community by Coda (@coda).</description>
    <link>https://dev.to/coda</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%2Forganization%2Fprofile_image%2F396%2F3b0f0f01-b434-43de-aec4-e1d711a01d54.png</url>
      <title>DEV Community: Coda</title>
      <link>https://dev.to/coda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coda"/>
    <language>en</language>
    <item>
      <title>10 features where Coda is 10X better than Notion in 2022</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Fri, 04 Mar 2022 19:21:37 +0000</pubDate>
      <link>https://dev.to/coda/10-features-where-coda-is-10x-better-than-notion-in-2022-60n</link>
      <guid>https://dev.to/coda/10-features-where-coda-is-10x-better-than-notion-in-2022-60n</guid>
      <description>&lt;p&gt;&lt;em&gt;See the full post with interactive elements &lt;a href="https://coda.io/@atc/ten-features-where-codaq-is-ten-times-better-than-notion" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let me be blunt: I work at Coda, and I’m 100% biased. I started using Coda during its stealth phase more than 5 years ago and frequently post videos about Coda on &lt;a href="https://www.youtube.com/channel/UC8DXcQiNj9RI2eeNycIETdA/featured" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you are looking for more “un-biased” reviews of Coda or Notion, I’d recommend checking out &lt;a href="https://www.g2.com/" rel="noopener noreferrer"&gt;G2&lt;/a&gt;, &lt;a href="https://www.capterra.com/" rel="noopener noreferrer"&gt;Capterra&lt;/a&gt;, or &lt;a href="https://www.trustradius.com/" rel="noopener noreferrer"&gt;TrustRadius&lt;/a&gt; (although those sites can contain bias as well since vendors typically send gift cards for reviews). There’s also this &lt;a href="https://coda.io/@john/coda-notion" rel="noopener noreferrer"&gt;less-biased article&lt;/a&gt; from my colleague. The most unbiased review would just be to ask your colleague what they think about Coda and Notion, browse places like &lt;a href="https://www.reddit.com/r/Notion/comments/ohtxl7/notion_vs_coda_2021/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt;, or check out &lt;a href="https://coda.io/@ben-[parker/the-notion-users-guide-to-coda-2022-edition" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; from someone who started in Notion and ended in Coda.&lt;/p&gt;

&lt;p&gt;Many people ask me and my colleagues what differentiates Coda from Notion and vice versa. As is the case with many SaaS software you use today, every tool has its pros and cons. To understand where I’m coming from, you need to know a little more about me. I have a background in financial analysis and &lt;a href="https://coda.io/@atc/from-one-spreadsheet-&amp;gt;nerd-to-another" rel="noopener noreferrer"&gt;love spreadsheets&lt;/a&gt;. So much so that I extend spreadsheets beyond what they were meant to do (balancing ledgers and whatnot for accounting folks). Beyond the simple comparison of features I share below, one key takeaway from this post is this: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can bend a tool to do what you want, as long as you’re willing to put up with the nuance, tedium, and complexity of bending the tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that preface, let’s get into the top 10 features where Coda is 10X better than Notion. If you prefer to watch a video of the top 10 features, click below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=MtLRjwyl77s" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FexE9Kn" alt="10 features where Coda is 10X better than Notion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Easier-to-write formulas.
&lt;/h2&gt;

&lt;p&gt;Lest you forget: you can bend a tool to any shape you want. For the Excel fans out there, you may think this formula is easy to write:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;=VLOOKUP(A2,Raw_Data!A1:C100,2,0)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I’m not going to lie, I do love me a good &lt;code&gt;VLOOKUP&lt;/code&gt; when I need to do some quick analysis. Here’s a quick comparison of doing a &lt;code&gt;VLOOKUP&lt;/code&gt; between Coda and Notion:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fivfp040o5ie8a9dfawgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fivfp040o5ie8a9dfawgq.png" alt="Coda formula for doing a vlookup"&gt;&lt;/a&gt; &lt;em&gt;Coda formula for lookups&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2olnq19y3q7s7vnerl8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2olnq19y3q7s7vnerl8v.png" alt="Notion's formula is not as intuitive as Coda's formula for doing a vlookup"&gt;&lt;/a&gt; &lt;em&gt;Notion “formula” for lookups&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the “Customers” table, we’re trying to find the total sales for each customer (this comes from the “Sales” table). In Coda, the formula looks like this: &lt;code&gt;Sales.filter(Customer ID=Customer ID).Total Sales&lt;/code&gt;. In Notion, you first do a &lt;code&gt;Sales Relation&lt;/code&gt; column and then do a rollup column called &lt;code&gt;Customer Sales&lt;/code&gt; to get the actual number of sales. This isn’t really a formula in Notion. It’s like the “no code” way of writing a formula. &lt;/p&gt;

&lt;p&gt;A more clear example of how writing formulas in Coda is easier might be in this simple example below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F24d9njyi3s2eqc4c7mt9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F24d9njyi3s2eqc4c7mt9.png" alt="Coda's formula for a basic IF THEN statement is similar to Excel and Google Sheets"&gt;&lt;/a&gt; &lt;em&gt;Coda formula for IF statement&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fecw1zhfxw49kknuc2w0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fecw1zhfxw49kknuc2w0m.png" alt="Notion's formula for an IF THEN statement is a little more complicated than Coda's formula since it requires the prop statement"&gt;&lt;/a&gt; &lt;em&gt;Notion formula for IF statement&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We’re trying to see if the customer name is equal to “Alice.” In both Coda and Notion, you reference the entire column name instead of cell references (like Excel and Google Sheets). The main drawback with Notion is that you have to add a &lt;code&gt;prop()&lt;/code&gt; function around each column name, which makes long formulas more difficult to parse. This could be an easy fix on Notion’s side to make their formulas easier to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Formulas that just do more in tables.
&lt;/h2&gt;

&lt;p&gt;Stretching formulas to do creative things is what I love about Excel and Google Sheets. That creativity is taken to the max in Coda. In the example above, let’s say we want a column to say “High” if that sales number is is highest of all sales, “Low” if the number is the lowest, and “N/A” for everything else:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fe1rmslo13e422rwtau0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fe1rmslo13e422rwtau0r.png" alt="Coda's formulas have line breaks, tabs, and spaces to make formulas easier to read and debug"&gt;&lt;/a&gt; &lt;em&gt;Coda formulas look pretty&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpxs83lgbfw55k6pa78qv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpxs83lgbfw55k6pa78qv.png" alt="Notion's formulas don't look as nice as Coda formulas since they are wrapped on one line and are more difficult to read."&gt;&lt;/a&gt; &lt;em&gt;Notion formulas wrap on 1 line&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Coda formula uses the &lt;code&gt;Switch&lt;/code&gt; &lt;a href="https://coda.io/formulas#Switch" rel="noopener noreferrer"&gt;function&lt;/a&gt; which prevents the need to do a nested &lt;code&gt;IF&lt;/code&gt; function. The &lt;code&gt;Max&lt;/code&gt; and &lt;code&gt;Min&lt;/code&gt; functions aren’t super special, but you can sort values in your current table and compare those values with a specific row. In the Notion example, the formula is doable, but requires a few “supporting columns” like the &lt;code&gt;All Sales&lt;/code&gt; relation, &lt;code&gt;Max Sales&lt;/code&gt; rollup, and &lt;code&gt;Min Sales&lt;/code&gt; rollup. Side note: &lt;em&gt;I wasn’t sure if this formula was even possible in Notion until I came across &lt;a href="https://www.reddit.com/r/Notion/comments/bpcy21/tables_referencing_a_max_from_another_table/" rel="noopener noreferrer"&gt;this Reddit thread&lt;/a&gt;&lt;/em&gt;. Then from there, you can write the nested &lt;code&gt;IF&lt;/code&gt; statement to see if that customer’s sales is the highest or lowest.&lt;/p&gt;

&lt;p&gt;I put these formula features as #1 and #2 because they show where Coda is better than Notion the most. Notion could come up with more flexible formulas that allow dynamic sorts and filters, but in the meantime the rollup and relation features will have to suffice. Again, you can always bend your tool to do what you want. &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Automations to handle recurring tasks &amp;amp; reminders.
&lt;/h2&gt;

&lt;p&gt;For most people out there, Coda’s automation feature is like the robot that does things for you every day or every week. It sends an update email, shows you your recurring tasks for the week, and can even send Slack messages. For the developers out there, it’s like a crontab. One of my favorite examples of automations being used in the wild is this &lt;a href="https://coda.io/@mick-niepoth/robot-pm-by-flatiron-school" rel="noopener noreferrer"&gt;Robot PM template&lt;/a&gt; by Mick Niepoth who set up a system to send reminders to his team on overdue tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhzfn81e1ps5k2j9heqsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhzfn81e1ps5k2j9heqsk.png" alt="Coda's Automation feature allows you to schedule tasks to start at certain times. This means you can easily do recurring tasks and reminders."&gt;&lt;/a&gt; &lt;em&gt;Coda’s Automation panel&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Watch for 20 seconds starting at 1:00 to see how automations work:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/88WY4Ri1VxI?t=60" rel="noopener noreferrer"&gt;&lt;img src="https://media.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%2Fqi6i2cxfkmcgkjoxq09y.png" alt="Coda Automations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;General automations aren’t available in Notion, but there are some creative workarounds for setting up recurring tasks and reminders. &lt;a href="https://thomasjfrank.com/how-to-create-recurring-tasks-repeat-due-dates-in-notion/" rel="noopener noreferrer"&gt;This one&lt;/a&gt; from Thomas Frank and &lt;a href="https://www.youtube.com/watch?v=rAEAsT35TjY&amp;amp;feature=emb_title" rel="noopener noreferrer"&gt;this video&lt;/a&gt; from Marie Poulin are worth checking out showing how they tried to build automations into their Notion workspaces:&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Full Integrations with 3rd-party services.
&lt;/h2&gt;

&lt;p&gt;In Coda, 3rd-party integrations are called &lt;a href="https://coda.io/gallery?filter=Packs" rel="noopener noreferrer"&gt;Packs&lt;/a&gt;. In Feb 2022, we announced &lt;a href="https://coda.io/@coda/the-doc-that-brings-it-all-together" rel="noopener noreferrer"&gt;the open Packs platform&lt;/a&gt; where anyone can create their own Pack and extend the power of Coda. The main difference between Coda’s Packs and Notion’s integrations is the ease of use. This is akin to Coda applying a “no code” layer on top of integrations. What does that mean?&lt;/p&gt;

&lt;p&gt;If you scroll up to bullet #1 where I mention the &lt;code&gt;VLOOKUP&lt;/code&gt; example, Coda lets you write a formula to do something similar to &lt;code&gt;VLOOKUP&lt;/code&gt;. Notion, on the other hand, abstracts the formula writing away and lets you click through menus to create relations and rollups to do something similar to &lt;code&gt;VLOOKUP&lt;/code&gt;. This is like Notion applying “no code” to doing a &lt;code&gt;VLOOKUP&lt;/code&gt;, where “no code” is a general term for making something a little more abstract. &lt;/p&gt;

&lt;p&gt;Both Coda and Notion have APIs, and it’s up to makers and builders to create integrations that the masses can use. In the case of integrations (that interact with the API), Coda has applied a “no code” approach to integrating with 3rd party apps. This means simple drag-and-drop to get your data into Coda and less fiddling with APIs. Watch for 30 seconds starting at 0:50 to see how you might integrate with Gmail:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/vjv9_gcqJoc?t=50" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FW8Istl" alt="Coda Packs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Coda’s Packs are standardized and the ease of using the GitHub Pack would be the same as using the &lt;a href="https://coda.io/packs/gmail-1004" rel="noopener noreferrer"&gt;Gmail&lt;/a&gt;, &lt;a href="https://coda.io/packs/twitter-1002" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, and yes, even the &lt;a href="https://coda.io/packs/notion-10229" rel="noopener noreferrer"&gt;Notion Pack&lt;/a&gt;. This table below shows the Yelp Pack in action. It allows you to see info about a restaurant with only the Yelp URL (see the Coda doc to interact with the table):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FIEbTIt" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FIEbTIt" alt="Yelp Coda Pack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even I was able to publish a Pack. My colleague and I published this Pack which simply shows you a live feed of all remote jobs from &lt;a href="https://coda.io/packs/we-work-remotely-jobs-10198" rel="noopener noreferrer"&gt;We Work Remotely&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/integrations/all" rel="noopener noreferrer"&gt;Notion’s integrations&lt;/a&gt; include Asana, GitHub, and a few others created by the community. The main difference is that the extent of the integration is a “live preview” of a card in Trello or issue in GitHub when you copy and paste a link into Notion (see “Link Previews” in this &lt;a href="https://www.notion.so/help/embed-and-connect-other-apps" rel="noopener noreferrer"&gt;help article&lt;/a&gt;). This screen in Notion shows all the “connected apps” available and it seems like you can see a table of your Trello cards or GitHub issues in a database in Notion, but this feature simply let’s you embed rich previews of your 3rd party data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FCTYzUY" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FCTYzUY" alt="Notion's integrations aren't truly integrations as they only let you see rich previews of your data from other 3rd party apps. In Coda, you can interact with your 3rd party apps and view data in a structured table."&gt;&lt;/a&gt; &lt;em&gt;Notion’s integrations only allow for rich previews &amp;amp; embeds&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;: Integrations (or Packs) in Coda are “full” integrations where you can view and sort your data from 3rd party apps, and take action in those apps by pushing a button in Coda (see the next bullet on buttons). Notion’s integrations are simply rich previews of your data (although this will change as Notion announced &lt;a href="https://www.notion.so/blog/synced-databases" rel="noopener noreferrer"&gt;synced databases&lt;/a&gt; in March 2022).     &lt;/p&gt;

&lt;p&gt;Community-driven directory sites do exist like &lt;a href="https://notionintegrations.com/" rel="noopener noreferrer"&gt;NotionIntegrations&lt;/a&gt;. You could integrate Notion with GitHub through &lt;a href="https://githubnotionsync.com/" rel="noopener noreferrer"&gt;this integration&lt;/a&gt; created by BeyondCode (letting you see all your GitHub data in a database), but this isn’t an “official” Notion integration. If there are any issues with the integration, you have to reach out to the BeyondCode team. &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Buttons that look like buttons and do stuff.
&lt;/h2&gt;

&lt;p&gt;Combined with formulas in bullets #1 and #2, buttons are one of the most powerful features in Coda. The main problem they solve for teams is &lt;strong&gt;accidental or incorrect data entry in a table&lt;/strong&gt;. Coming from the Excel or Google Sheets worlds, you typically create buttons by using &lt;a href="https://support.microsoft.com/en-us/office/assign-a-macro-to-a-form-or-a-control-button-d58edd7d-cb04-4964-bead-9c72c843a283" rel="noopener noreferrer"&gt;Form Controls&lt;/a&gt; which requires you to know how to write macros. In Coda, once you’ve become familiar with a few formulas, you get the added benefit using that same formula language in a button.&lt;/p&gt;

&lt;p&gt;For instance, look at this example table below of tier 1 customers you might have set up for your sales team to call:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2F2dy5na" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2F2dy5na" alt="coda table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s a pretty basic table and if an Account Exec calls the customer, they would check off the checkbox in the &lt;code&gt;Called?&lt;/code&gt; column. There’s some basic conditional formatting so that it’s clear which customer has been called.&lt;/p&gt;

&lt;p&gt;If you’ve set up a Google Sheet or Notion workspace for your team, the checkbox is probably the most advanced you’ve gotten with making your spreadsheet or workspace “user friendly” to your teammates. Let’s look at the same table now with a button instead of a checkmark:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2F8bHVVQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2F8bHVVQ" alt="coda table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That green button just makes the list of customers a little easier to interact with versus checking off the checkbox column. We could even hide the Call check column from view to de-clutter the table some more. Behind the scenes, formulas in the Called? button column control the text that shows up on the button and the checking of the checkbox in the Call check column. Maybe you want to have a giant button outside the table that checks off all customers in one go:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FDhrdxQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FDhrdxQ" alt="big coda button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need a more lightweight button without all the formulas (but still want a nice looking button), you can add a simple reaction button into your tables or doc. These reaction buttons are nice visual indicators letting your teammates know that you’ve approved, acknowledged, or read something. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FnmmzQd" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FnmmzQd" alt="Coda reactions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.notion.so/help/template-buttons" rel="noopener noreferrer"&gt;template button&lt;/a&gt; is the only native button in Notion that lets you make copies of a template you’ve built. There are work arounds for creating button-like images in Notion like this example where you create &lt;a href="https://www.theplanningpanda.com/single-post/how-to-create-aesthetic-buttons-in-notion" rel="noopener noreferrer"&gt;actual images&lt;/a&gt; in a gallery database view. Apparently there’s also a button widget you can use via &lt;a href="https://indify.co/" rel="noopener noreferrer"&gt;Indify&lt;/a&gt; (3rd party), but it’s not a native Notion feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. A formula editor with new line breaks, spaces, and tabs.
&lt;/h2&gt;

&lt;p&gt;If you’re a heavy spreadsheet users, you’ve probably had to write a long nested IF formula with multiple true and false branches. IF functions exist in Coda and Notion too! However, in Coda there is a big formula editor that lets you see your formulas more clearly. This is a feature that is similar to bullet #1 where formulas in Coda are just easier to write.&lt;/p&gt;

&lt;p&gt;If we go back to the example from bullet #1, here’s a comparison of what a long-ish formula looks like in Coda and Notion:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1hstcz78thsjm4hbf1f0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1hstcz78thsjm4hbf1f0.png" alt="Coda's formula editor can be expanded to show a really long formula. Line breaks and spaces make formulas easier to read and debug if there are mistakes."&gt;&lt;/a&gt; &lt;em&gt;Coda’s formula editor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2jmndpgqzkoxfw3eovtn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2jmndpgqzkoxfw3eovtn.png" alt="Notion's formula editor is just one box and the formula is wrapped on one line, making it less easy to use and read compared to Coda's formula editor."&gt;&lt;/a&gt; &lt;em&gt;Notion’s formula editor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These are the formulas for Coda and Notion for figuring out the “high” and “low” sales from bullet #1. The Coda formula could’ve been written in one long line like the Notion formula, but aren’t things just nicer when you have line breaks and indents? It makes debugging formulas your colleagues write way easier when everything is not written on one long wrapped line.&lt;/p&gt;

&lt;p&gt;If you are writing super long formulas, another added benefit in Coda is you can pop open a big window while you’re editing the formula. This gives your more whitespace to see where your formula goes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnnpd54fd0lpc1lq1zy8u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnnpd54fd0lpc1lq1zy8u.gif" alt="Expand Coda's formula editor to give yourself more whitespace to write and edit your formulas."&gt;&lt;/a&gt; &lt;em&gt;Coda’s formula editor can be expanded&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Detailed layout when expanding rows in tables.
&lt;/h2&gt;

&lt;p&gt;You can already customize the look and feel of individual pages in both Coda and Notion. Embed images, dragn-and-drop elements, and &lt;a href="https://community.coda.io/t/launched-align-content-side-by-side-with-page-layout/27809" rel="noopener noreferrer"&gt;multi-column layout&lt;/a&gt; are some of the common features for customizing pages. But what about tables? &lt;/p&gt;

&lt;p&gt;The use case here is when you have a really wide table with a lot of columns. When you want to “view” a specific row in the table, you don’t want to force your teammate to scroll endlessly to the right to view all the data. When you “expand” the row, you want to see more details about that specific row in a user-friendly way. Here’s a comparison of what a detailed row layout looks in Coda and Notion using the “Customers” table example from bullet #1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkhpw12mnc0t8smkcn9x2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkhpw12mnc0t8smkcn9x2.png" alt="Coda's detail layout for a row can be customized with columns and images. This makes the row detail easier to read and more user friendly for your teammates and colleagues."&gt;&lt;/a&gt; &lt;em&gt;Coda’s detail layout for a row&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F961kcdusiwdhkypfnavt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F961kcdusiwdhkypfnavt.png" alt="Notion's row detail for a row in a table is pretty limited compared to Coda. You can only organize column names up and down."&gt;&lt;/a&gt; &lt;em&gt;Notion’s detail layout (page) for a row&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The customizable row layouts allow you to view the columns in your table in a multi-column layout. If you have pictures in your table, those pictures can show up in the row layout as a “cover” image or a “profile picture” (in the use cases where you have a list of people). These custom layouts were modeled off of other popular websites that show lists of data like Yelp:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwsjc1b5luf9ekmzd51en.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwsjc1b5luf9ekmzd51en.png" alt="Coda's custom layouts for row details. This allows you to make row layouts similar to websites and makes your row layout easier to read."&gt;&lt;/a&gt; &lt;em&gt;Quick custom layouts for viewing expanded rows in Coda.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Back to the “Customers” table in Notion, expanding the row gives you a detailed layout, but the most you can do in terms of customization is moving columns up and down:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxy7nw340vprbggkmdoqz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxy7nw340vprbggkmdoqz.gif" alt="You can only move columns up and down in Notion's row detail layout making the layout more restrictive compared to Coda."&gt;&lt;/a&gt; &lt;em&gt;Only move columns and up and down in Notion’s row detail layout&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s small feature in the grand scheme of things, and Notion could probably easily add this feature in the future to their detailed row layouts. This feature may not be that interesting for the power users and makers out there since you’re familiar with the shape of your data and might be used to scrolling through your tables. This feature is geared towards &lt;strong&gt;teams&lt;/strong&gt; where you need a way to show a ton of data to your teammates and:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Want to show the relevant columns to a teammate in a user-friendly way.&lt;/li&gt;
&lt;li&gt;Don’t want to show all the columns from the table that don’t matter for the teammate’s job.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. Sorting animation during Zoom meetings.
&lt;/h2&gt;

&lt;p&gt;Sorting and filtering data in a table is pretty standard. How that data gets sorted is the feature that’s worth calling out in Coda. This is where a simple sorting animation makes your data alive as your teammates interact with the data Let’s consider this scenario:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are leading a &lt;a href="https://coda.io/@atc/project-sprint-retrospective[" rel="noopener noreferrer"&gt;project retrospective&lt;/a&gt; and want to figure out what went well/didn’t go well last quarter with your team. You’ve set up a table for people in your meeting to add their ideas. In the Zoom meeting, you discover your teammate has already added a few of her ideas on what could go better this quarter to the table. These ideas end up getting looked at first which biases what people think about during the meeting. During the meeting, your other talkative teammate hogs the Zoom and rambles about their ideas for what didn’t go well last quarter. Most people in the Zoom are silent. &lt;/p&gt;

&lt;p&gt;To even the playing field, people should be able to add their ideas and silently vote on them. This allows the best ideas to bubble to the top which have the most “votes.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Coda’s &lt;a href="https://coda.io/@coda/meetings/voting-table-8" rel="noopener noreferrer"&gt;voting table template&lt;/a&gt; is one of the simplest and most useful templates to use for synchronous meetings that happen over Zoom, Teams, etc. See the example below where a bunch of questions have been added. As the meting leader, you want to know which ideas are the most important to your teammates. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fw4axqzbb21ihb915ff3g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fw4axqzbb21ihb915ff3g.gif" alt="Coda sorting table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll notice a slight animation as the table resorts and puts Idea #2 to the top of the table. Imagine 10, 50, or 100 people voting on ideas at once and seeing the table re-sort in real-time. This is exactly what Shipt did with their &lt;a href="https://coda.io/@dave-huynh/how-shipt-encourages-participation-in-retros" rel="noopener noreferrer"&gt;team retro template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You don’t have to re-sort the table like you would in Google Sheets or Excel. This slight animation shows people on the Zoom meeting that stuff is happening during the meeting and encouraged to participate. &lt;/p&gt;

&lt;p&gt;In Notion, sorting just kind of happens as values are being updated in your table. Going back to our “Customers” table, I’ve set up a sort on the &lt;code&gt;Customer ID&lt;/code&gt; column to always sort from least to greatest:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fy8ofnxj37knl0vtylp1w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fy8ofnxj37knl0vtylp1w.gif" alt="When sorting in a database in Notion, the rows get sorted quickly and abruptly making them less engaging during a meeting."&gt;&lt;/a&gt; &lt;em&gt;Notion’s rows get sorted abruptly after you change values&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As I change the &lt;code&gt;Customer ID&lt;/code&gt; column number, the table gets sorted from least to greatest. The sorting happens abruptly. All of a sudden, you see Alice at the bottom and then Bob at the top. With a simple animation, the sorting feels more interactive and less jarring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worst case scenario&lt;/strong&gt;: Small features like this make whatever tool you’re using during meetings a little more enjoyable and interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best case scenario&lt;/strong&gt;: You get to hear what’s actually on the minds of your teammates since the feature encourages everyone to vote, participate, and get their “voice” heard. &lt;/p&gt;

&lt;h2&gt;
  
  
  9. Native forms (and support for them).
&lt;/h2&gt;

&lt;p&gt;This feature is similar to bullet #4 on integrations and #5 on buttons. &lt;/p&gt;

&lt;p&gt;The use case here is you want your teammates (or external vendors) to fill out a form to populate a table. That teammate or vendor most likely is not a Coda or Notion user yet so you just need a simple form that they can load on their computer or phone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5304nwbo9ii6qbtxuq7n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5304nwbo9ii6qbtxuq7n.gif" alt="Forms are a native feature in Coda. This means you get the best support if you have any issues with your Coda forms."&gt;&lt;/a&gt; &lt;em&gt;Native forms in Coda&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.coda.io/t/launched-forms/20040" rel="noopener noreferrer"&gt;Forms in Coda&lt;/a&gt; are a native feature which means our support team can help you troubleshoot any and all issues relating to creating and publishing your form. Prior to the forms feature, makers would create forms in Google Forms or Typeform and connect the responses to their Coda doc with Zapier. With native Forms in Coda, there’s no more overhead with setting up (and paying for) a 3rd party service like Zapier to connect things together. &lt;a href="https://coda.io/form/Untitled-Form_dmoUI44euHr" rel="noopener noreferrer"&gt;This is a simple form created in Coda&lt;/a&gt; with one question embedded (responses will show up in the &lt;a href="https://coda.io/@atc/ten-features-where-coda-is-ten-times-better-than-notion/feedback-2" rel="noopener noreferrer"&gt;Feedback page&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;In Notion, there are 3rd-party add-ons for creating forms. Some of the popular add-ons include &lt;a href="https://notionforms.io/" rel="noopener noreferrer"&gt;NotionForms&lt;/a&gt;, &lt;a href="https://workspace.google.com/marketplace/app/form_to_notion/55933174335" rel="noopener noreferrer"&gt;Form to Notion&lt;/a&gt; (Google Workspace add-on for Google Forms), and &lt;a href="https://chilipepper.io/" rel="noopener noreferrer"&gt;Chilipepper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For most use cases on a small team, NotionForms’ Basic plan may be fine for your use case (it’s free). For bigger teams who need forms for multiple workspaces, you’ll need to sign up for their $15/mo plan. Again, for larger enterprises this cost is probably negligible. If you or your teammate wants to build out a complex form or run into issues with your form, who do you turn to for support? Someone from Notion’s customer support team may be able to assist you with the form. But since this is a 3rd-party add-on, you’re most likely going to contact the support team at NotionForms.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Cost savings on a team plan for bigger teams.
&lt;/h2&gt;

&lt;p&gt;If you work for a big enterprise or well-funded company who doesn’t care about their SaaS and software bills, this bullet point might be irrelevant. For the other folks out there who are cost-conscious and making a considered decision about which tool to put through the gauntlet of your IT and Security teams, this bullet point might resonate. &lt;/p&gt;

&lt;p&gt;Let’s take a look at the Team plans for both Coda and Notion (straight off the pricing page):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffx91oc85ik954yf2k1z4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffx91oc85ik954yf2k1z4.png" alt="Coda's team pricing plan allows for unlimited editors and viewers. You only pay for users who create docs."&gt;&lt;/a&gt; &lt;em&gt;Coda’s team pricing plan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpoeb2t5zg9hub9q951yi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpoeb2t5zg9hub9q951yi.png" alt="Notion's team plan is a traditional SaaS model where you have to pay for every user of Notion. This makes Notion more expensive for bigger teams."&gt;&lt;/a&gt; &lt;em&gt;Notion’s team pricing plan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we look at the true monthly cost (not the monthly cost after buying an annual plan), it’s Coda’s &lt;strong&gt;$36/user&lt;/strong&gt; vs. Notion’s &lt;strong&gt;$10/user&lt;/strong&gt;. That seems like a lot for Coda. But of course, it’s all in the details. &lt;/p&gt;

&lt;p&gt;If you are just testing Coda or Notion out on a team of &amp;lt;10, I think Notion may actually be the more economical choice. Here’s a breakdown of what costs might look like for two types of teams:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Small team&lt;/strong&gt; of 2 marketing ops leads and their 5-7 marketing colleagues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple teams&lt;/strong&gt; in a company of 200+ people where 75 people need to be able to create and edit pages and the remaining 100+ just need to make light edits or view stuff&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FT4I9gu" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcoda-us-west-2-droplr-storage.s3.us-west-2.amazonaws.com%2Ffiles%2Facc_1218270%2FT4I9gu" alt="Coda vs Notion pricing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;: The key distinction here between Coda and Notion is that in Coda, &lt;strong&gt;an editor has more powers than a guest does in Notion&lt;/strong&gt;. A Coda &lt;em&gt;editor&lt;/em&gt; can create pages, edit formulas, and do all the things a &lt;em&gt;doc maker&lt;/em&gt; can do except for creating Coda docs. Most people in a company may not need to create Coda docs. Notion is inexpensive to use for small teams, but Coda is a more economical option in the long run for serious cross-functional and company-wide usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  100 other features not mentioned.
&lt;/h2&gt;

&lt;p&gt;As I stated at the top, I’m biased. There are hundreds of other features in Coda and Notion I didn’t mention. There are also features that make Notion better than Coda. It all depends on your team use case and how much time you want to put into bending the tool to do XYZ for your team. &lt;/p&gt;

&lt;p&gt;For more unbiased reviews and feature comparisons, I’d consider taking a look at this &lt;a href="https://www.reddit.com/r/Notion/collection/5e7766e5-61fb-4aac-9d22-c06125ea596a/" rel="noopener noreferrer"&gt;Reddit collection&lt;/a&gt; from the r/Notion reddit (shout out to /u/ben-something) for compiling!).&lt;/p&gt;

&lt;p&gt;While this Notion vs. Coda comparison is old (from 2020), &lt;a href="https://www.reddit.com/r/Notion/comments/gyxq82/notion_vs_coda_in_2020/" rel="noopener noreferrer"&gt;this thread&lt;/a&gt; in the collection confirms some of the features I mentioned in the post (see &lt;a href="https://www.reddit.com/r/Notion/comments/gyxq82/notion_vs_coda_in_2020/fvqwmji/?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3" rel="noopener noreferrer"&gt;this response&lt;/a&gt; from /u/makaike) like buttons, better formulas, and detailed row layouts. If you’re on Notion and thinking about trying Coda, check out the &lt;a href="https://coda.io/packs/notion-10229" rel="noopener noreferrer"&gt;Notion Pack&lt;/a&gt; and this accompanying &lt;a href="https://coda.io/@leandro-zubrezki/giving-notion-codas-superpowers" rel="noopener noreferrer"&gt;template&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have any comments, questions, or corrections? Leave them in this &lt;a href="https://twitter.com/bigal123/status/1499447892507078662" rel="noopener noreferrer"&gt;Twitter thread&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>coda</category>
      <category>notion</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to export and analyze Jira issues in Google Sheets vs. Coda</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Fri, 04 Sep 2020 19:46:53 +0000</pubDate>
      <link>https://dev.to/coda/how-to-export-and-analyze-jira-issues-in-google-sheets-vs-coda-4jo0</link>
      <guid>https://dev.to/coda/how-to-export-and-analyze-jira-issues-in-google-sheets-vs-coda-4jo0</guid>
      <description>&lt;p&gt;Once your Jira backlog of issues grows to a certain point, you may want to view all your issues in another format like a spreadsheet to figure out what your team should focus on. In a spreadsheet, you can quickly filter, sort, and organize issues by multiple dimensions like priority, due date, and status. The issue is that the spreadsheet is only a &lt;em&gt;snapshot&lt;/em&gt; of your Jira issues. As your team makes updates in Jira, those updates to sync to your spreadsheet unless you use an add-on like &lt;a href="https://support.atlassian.com/jira-core-cloud/docs/use-jira-cloud-for-sheets/"&gt;Jira Cloud for Sheets&lt;/a&gt;. An alternative is to use a &lt;a href="https://coda.io/packs/jira"&gt;Jira Packs table&lt;/a&gt; in Coda to sync your data from Jira in a table format.&lt;/p&gt;

&lt;p&gt;In this tutorial, I’m going to show you how you can do a regular export of Jira issues into Google Sheets and how to analyze issues once they’ve been exported. I’ll also show how you can do a similar type of export in Coda &lt;em&gt;except&lt;/em&gt; the issues in Coda will stay synced with your Jira project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Skip straight to the video tutorial below and check out this template for the part of the tutorial focused on syncing Jira issues into Coda:&lt;/em&gt; &lt;a href="https://coda.io/@atc/jira-backlog-template-for-tutorial"&gt;https://coda.io/@atc/jira-backlog-template-for-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/MbFsaSiF72I"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Exporting Jira issues to Google Sheets
&lt;/h3&gt;

&lt;p&gt;This is assuming you are using the hosted version of Jira. Before you can export, you need to &lt;a href="https://support.atlassian.com/jira-core-cloud/docs/save-your-search-as-a-filter/"&gt;create a filter&lt;/a&gt; of your issues for your project. Under the &lt;strong&gt;Filters&lt;/strong&gt; menu, click on &lt;strong&gt;View all filters&lt;/strong&gt; and you’ll see a &lt;strong&gt;Create filter&lt;/strong&gt; button to the right:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mPCS-Xxr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AGrgcQZ7j6Qkkuuex" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mPCS-Xxr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AGrgcQZ7j6Qkkuuex" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you’ve created the filter for your project, you’ll see an Excel and Google Sheets icon near the top of the screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OGiakpqR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AuAtHh53FVHuFDdog" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OGiakpqR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AuAtHh53FVHuFDdog" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will give you a clean export of your Jira issues. An important note:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This export only gives you a snapshot of your Jira issues. Any updates you make in Jira will not get reflected in Google Sheets and vice versa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your new Google Sheet will contain two worksheets: &lt;strong&gt;About&lt;/strong&gt; and &lt;strong&gt;Your Jira Issues&lt;/strong&gt;. The &lt;strong&gt;About&lt;/strong&gt; page just contains some images about using &lt;a href="https://support.atlassian.com/jira-core-cloud/docs/use-jira-cloud-for-sheets/"&gt;Jira Cloud for Google Sheets&lt;/a&gt; (useful if you want to keep data in-sync from Jira to Google Sheets). The &lt;strong&gt;Jira Query&lt;/strong&gt; shows up on this worksheet which is useful if you are using &lt;a href="https://www.atlassian.com/software/jira/guides/expand-jira/jql#jql-syntax"&gt;Jira Query Language&lt;/a&gt; (JQL) to query your Jira project and/or using the Jira Cloud for Google Sheets add-on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u6QRYmIb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABi85P7iBja1oL86c" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u6QRYmIb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABi85P7iBja1oL86c" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Playing with your Jira issues in Google Sheets
&lt;/h3&gt;

&lt;p&gt;Getting a tabular view of your Jira issues is really useful since you can see all the fields for an issue organized along the top of the spreadsheet. A logical next step here is to filter your list of issues by a field like Status. Here, I’m setting up a filter to see all issue that have a Status of “To Do.” You could of course apply multiple filters depending on what you want to see (all issues with a Status of “To Do” and Created on 8”/16/20”).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KggONDhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ASVhSTmg6oYVjIv-G" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KggONDhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ASVhSTmg6oYVjIv-G" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dealing with teammates who want to filter Jira issues
&lt;/h3&gt;

&lt;p&gt;The issue with doing a basic filter like this is that your teammate may want to see the issues assigned to him or her and perhaps color those rows a certain way. Every time your teammate jumps into the Google Sheet and applies their own filters, this will “overwrite” your own filter that you applied.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Filter Views&lt;/strong&gt; in Google Sheets come into play. You can tell your teammates that once they have filtered the list of issues to their heart’s desire, have them create a &lt;strong&gt;Filter View&lt;/strong&gt; by clicking the &lt;strong&gt;Data&lt;/strong&gt; , &lt;strong&gt;Filter views&lt;/strong&gt; , then &lt;strong&gt;Save as filter view&lt;/strong&gt;. Below, I have filtered the list of issues to Status of “To Do” and the Assignee is “Polly Rose.” I then create a filter view called “Polly’s issues”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mzdfh29b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AYVwSRhGgoe_YIvSG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mzdfh29b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AYVwSRhGgoe_YIvSG" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if a teammate goes into the Google Sheet, they can click on &lt;strong&gt;Data&lt;/strong&gt; , &lt;strong&gt;Filter Views&lt;/strong&gt; , and see a list of filtered views created. They can then pick the filtered view they have created without messing up anyone else’s filters. When you close out the filtered view, the list just goes back to the full list of unfiltered Jira issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2iJ3sPMT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ARp_9uY_h7ox4ej8_" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2iJ3sPMT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ARp_9uY_h7ox4ej8_" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating copies of your issue list into multiple worksheets and keeping data synced between worksheets
&lt;/h3&gt;

&lt;p&gt;This list of filtered views could grow quite large, so another option is to create multiple copies of your list of issues and perhaps each worksheet is meant for a specific teammate, only contains issues of a certain Status, or some other field. It depends on the structure and needs of your team.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The big question is this: &lt;em&gt;does the list of issues need to be synced across worksheets in your Google Sheet?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the purpose of exporting your Jira issues to Google Sheets is to report and analyze issues, then this question is not important. My guess is most people are exporting into Google Sheets for this purpose, and doing the actual “work” of updating and logging issues in Jira directly. However, the power of the spreadsheet is that you can add columns and with custom formulas that calculate certain metrics off or your Jira issues.&lt;/p&gt;

&lt;p&gt;You could create a formula to calculate the number of days between when the issue was reported and when the issue was last updated. Or a formula that groups issues into the Assignee’s team which means you have a table somewhere in your Google Sheet mapping team member to team (and you do a VLOOKUP to the team name).&lt;/p&gt;

&lt;p&gt;With the above scenarios, you’ll have to find a way to keep your worksheets in sync with each other so that formulas get applied to &lt;em&gt;all worksheets&lt;/em&gt; and not just one worksheet where you’ve written the formula. A common solution to this: use the QUERY &lt;a href="https://support.google.com/docs/answer/3093343?hl=en"&gt;function&lt;/a&gt; in Google Sheets so that each copy of the main list of issues is not a direct copy, but rather a real-time query of the main list of issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S-Ca4GMk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Aa-gYcLMqu2kZ_I-s" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S-Ca4GMk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Aa-gYcLMqu2kZ_I-s" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The syntax looks very similar to SQL, and in this case assume the “Your Jira Issues” worksheet is the main table of issues that won’t be changed. The columns A:L are simply the column in this worksheet that contain my data, but you may have to expand the column reference if you continually add more custom formulas to your main issue list.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grouping your issues in a PivotTable
&lt;/h3&gt;

&lt;p&gt;One final strategy for viewing and analyzing your Jira issues is by creating a PivotTable of your Jira issues. This strategy is similar to the QUERY function in that the PivotTable will always pick up any new data that is added to the main list of issues. I don’t think this is a common scenario since this is just a snapshot of your Jira issues, but you may have a recurring task of exporting Jira issues into Google Sheets which leads to new issues getting added into Google Sheets.&lt;/p&gt;

&lt;p&gt;This use case of PivotTables is non-traditional since I won’t be aggregating any dimension in the “Values” of the PivotTable. The PivotTable could be interesting if you want to see how Story Point Estimate, for instance, changes depending on how your pivot your data. All I’m doing below is pivoting by Status so I can see all my issues grouped by a certain status:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ARwTlfJN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Au4--QfBIr1n9cDk9" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ARwTlfJN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Au4--QfBIr1n9cDk9" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get this view of my Jira issues, I’m only adding dimensions to the “Rows” in the PivotTable and unchecking the “Show totals” box so I can get a clean view of the issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2HBEUdJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A-e1hWNUMiHNwXX43" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2HBEUdJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A-e1hWNUMiHNwXX43" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Exporting and syncing Jira issues into Coda
&lt;/h3&gt;

&lt;p&gt;While I could do a simple copy and paste from the Google Sheet into a Coda table, the main benefit of Coda is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Updates in Jira will get synced into a table in Coda&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As mentioned above, there is a special type of table called Packs tables, which are tables that allows you to visualize tabular data from popular tools like Jira, Gmail, and Google Calendar in real time. In this case, I’m creating a &lt;a href="https://coda.io/packs/jira"&gt;Jira Packs table&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CbWM8qm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AFLHYENkw4DSEUWTd" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CbWM8qm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AFLHYENkw4DSEUWTd" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click on the &lt;strong&gt;Options&lt;/strong&gt; in the table, there are a variety of settings that let you control &lt;em&gt;how often&lt;/em&gt; data is synced over from Jira and &lt;em&gt;what data&lt;/em&gt; is actually synced over:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7gFTuz7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/906/0%2AzSf--_L6jtbt8n8I" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7gFTuz7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/906/0%2AzSf--_L6jtbt8n8I" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some options to choose from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Refresh rate:&lt;/strong&gt; Manual or every day/hour&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Table limit:&lt;/strong&gt; How many rows to sync over (may want to limit if you have thousands of Jira issues)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project name:&lt;/strong&gt; Sync over issues only from a specific project&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include sub-tasks:&lt;/strong&gt; Jira issues can be broken out into sub-issues, so know the parent or child of an issue may be important for your workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JQL Query:&lt;/strong&gt; Further customize exactly what issues get synced over with JQL&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding additional attributes from Jira issues to Coda
&lt;/h3&gt;

&lt;p&gt;Each issue in the Jira Packs table is a rich reference to the actual issue in your Jira instance. When you hover of an issue, you can see all the other attributes for that issue regardless if that attribute has a value. You can add those attributes to your Coda table in case you decide to use that attribute in the future in Jira:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RgbBPTP3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ATXOogUXDzWwStS3p" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RgbBPTP3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ATXOogUXDzWwStS3p" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualizing Jira issues in Coda
&lt;/h3&gt;

&lt;p&gt;Once the data is synced over, you can do spreadsheet-like things with the table. The most powerful feature for most teams’ workflows is creating &lt;em&gt;views&lt;/em&gt; off of the main table of Jira issues. This is similar to creating multiple worksheets of the same list of issues in Google Sheets. The difference is that Coda tables and views are always connected, so any changes in one view or in the main table are automatically propagated to all other connected views. This prevents the need to use QUERY in Google Sheets or some other workaround to keep data synced between worksheets.&lt;/p&gt;

&lt;p&gt;This view below is built off the same list of issues but grouped across two dimensions: Assignee and Status. You can see this view of Jira issues in &lt;a href="https://coda.io/@atc/jira-backlog-template-for-tutorial/backlog-by-assignee-3"&gt;this page&lt;/a&gt; of the template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nc914wLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AnjIN_u8jUXV7LhAe" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nc914wLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AnjIN_u8jUXV7LhAe" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on who you select as the Assignee, a chart below updates showing the Issues and Story Point Estimate for that person:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bU1KNv1W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AD5ZNq2B-ksNPsNUZ" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bU1KNv1W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AD5ZNq2B-ksNPsNUZ" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom columns built off of Jira issues
&lt;/h3&gt;

&lt;p&gt;In the Planned completion column, I want to communicate to the broader team when this issue might get fixed. Adding a custom field like this to your Jira project can be complicated, and in Coda it’s simply just adding another column. There is no formula in this column, but rather a value (eg. Q4, Q1, Q2) that my team has added after prioritizing and grooming our issues list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6I1zMil9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABTANhDEljwRUfg_2" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6I1zMil9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABTANhDEljwRUfg_2" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once I have this column in place, I can group by this column (think PivotTable) and completely change the layout of how my data looks to a kanban board. This is another view of the same list of Jira issues but now I can move issues around from one list to another depending on when I expect the Planned completion date to be:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RJPiWLh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2As3NC9Va-toDRy3Mf" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RJPiWLh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2As3NC9Va-toDRy3Mf" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Jira issues are in sync. Always.
&lt;/h3&gt;

&lt;p&gt;The key takeaway is that my team can continue working in Jira, and any of these custom views, columns, and formulas will update automatically. Certain teams or external stakeholders may need to see Jira issues “rolled up” into some report or analysis, and Jira doesn’t provide the exact reporting you need. Those team members can see Jira issues the way they want in Coda.&lt;/p&gt;




</description>
      <category>coda</category>
      <category>productivity</category>
      <category>googlesheets</category>
      <category>jira</category>
    </item>
    <item>
      <title>How to sync data from Coda to Google Sheets (and vice versa) with Google Apps Script tutorial</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Mon, 04 May 2020 17:56:22 +0000</pubDate>
      <link>https://dev.to/coda/how-to-sync-data-from-coda-to-google-sheets-and-vice-versa-with-google-apps-script-tutorial-506m</link>
      <guid>https://dev.to/coda/how-to-sync-data-from-coda-to-google-sheets-and-vice-versa-with-google-apps-script-tutorial-506m</guid>
      <description>&lt;h2&gt;
  
  
  Two new scripts
&lt;/h2&gt;

&lt;p&gt;Last year I published &lt;a href="https://coda.io/@atc/how-to-sync-data-between-coda-docs-and-google-sheets-using-googl"&gt;a tutorial&lt;/a&gt; on how to sync data between two Coda docs and data between two Google Sheets. What was missing from the tutorial was how to sync data between a &lt;strong&gt;Coda doc&lt;/strong&gt; and a &lt;strong&gt;Google Sheet&lt;/strong&gt;. Writing these scripts was definitely more challenging than the original script I wrote for syncing two Coda docs since the data model for Coda is different from Google Sheets. Please read the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir#_lueHe"&gt;caveats&lt;/a&gt; below about these scripts to learn about some of the roadblocks I encountered when writing these scripts.&lt;/p&gt;

&lt;p&gt;If you are reading this, chances are you have a lot of experience with Google Sheets, Coda, and perhaps the &lt;a href="https://coda.io/developers/apis/v1beta1"&gt;Coda API&lt;/a&gt;. I’m going to skip the introduction to Coda as I did with the &lt;a href="https://coda.io/@atc/how-to-sync-data-between-coda-docs-and-google-sheets-using-googl"&gt;last tutorial&lt;/a&gt; and get straight to the point on how you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sync data from &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sync data from &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;If you want to skip right to using the Google Apps Scripts, go to the other two pages in this doc (mentioned above) or go to&lt;/em&gt; &lt;a href="https://github.com/albertc44/coda-google-apps-script"&gt;&lt;em&gt;this repo&lt;/em&gt;&lt;/a&gt; &lt;em&gt;which contains all four scripts for syncing data (PRs welcome). Here are two video tutorials if you prefer a visual tutorial.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Coda to Google Sheets
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mAdAe8GVCdA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Sheets to Coda
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xVWu9jdBm_U"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;There are some limitations to the scripts which I’ll discuss later on in this blog post, but these are the main features for each script:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq#_luV4e"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;New rows that get &lt;strong&gt;added or deleted&lt;/strong&gt; in your Coda table will also get added or deleted in Google Sheets&lt;/li&gt;
&lt;li&gt;Existing rows that get &lt;strong&gt;updated&lt;/strong&gt; in Coda will also get updated in Google Sheets&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;re-arrange the columns&lt;/strong&gt; in your Google Sheet and the sync will still sync the appropriate columns in your Google Sheet&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;add or insert new columns&lt;/strong&gt; in your &lt;strong&gt;Google Sheet&lt;/strong&gt; and write formulas in these new columns&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;add or insert new columns&lt;/strong&gt; in your table in &lt;strong&gt;Coda&lt;/strong&gt; and these columns won’t get synced to Google Sheets (unless you create a new column in Google Sheets with the same column name as the one in your Coda table)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;New rows that get &lt;strong&gt;added or deleted&lt;/strong&gt; in your Google Sheet worksheet will also get added or deleted in your Coda table&lt;/li&gt;
&lt;li&gt;Existing rows that get &lt;strong&gt;updated&lt;/strong&gt; in your Google Sheet worksheet will also get updated in Coda&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;sort and filter&lt;/strong&gt; the rows in your target Coda table and the script will still add, delete, and update the appropriate rows in Coda&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;add rows&lt;/strong&gt; to your Coda table and not get them deleted on the sync by adding a “Do not delete” &lt;a href="https://help.coda.io/en/articles/1235680-overview-of-column-formats#types-of-column-formats"&gt;checkbox column&lt;/a&gt; in your Coda table that is set to &lt;code&gt;true&lt;/code&gt; (more about this later in the post)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the features in the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script also apply to the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; script, but I haven’t fully tested every use case. If you see any bugs, please add them to the repo’s &lt;a href="https://github.com/albertc44/coda-google-apps-script/issues"&gt;issues list&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup: Coda to Google Sheets script
&lt;/h2&gt;

&lt;p&gt;Starting in &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js#L9"&gt;line 9&lt;/a&gt; to &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js#L14"&gt;line 14&lt;/a&gt; of the &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js#L10"&gt;coda_to_sheet.js&lt;/a&gt; script, you’ll need to enter in some of your own data to make the script work. Step-by-step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://script.google.com/home"&gt;script.google.com&lt;/a&gt; and create a new project and give your project a name.&lt;/li&gt;
&lt;li&gt;Go to Libraries then Resources and paste the following string of text/numbers into the library field: &lt;code&gt;15IQuWOk8MqT50FDWomh57UqWGH23gjsWVWYFms3ton6L-UHmefYHS9Vl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click Add and then select a version of the library to use (as of May 2020, version 8 is the latest)&lt;/li&gt;
&lt;li&gt;Copy and paste the &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js"&gt;entire script&lt;/a&gt; into your Google Apps Script project and click File then Save.&lt;/li&gt;
&lt;li&gt;Go to your Coda &lt;a href="https://coda.io/account"&gt;account settings&lt;/a&gt;, scroll down until you see “API SETTINGS” and click Generate API Token. Copy and paste that API token into the value for &lt;code&gt;YOUR_API_KEY&lt;/code&gt; in the script. &lt;em&gt;Note: do not delete the single apostrophes around&lt;/em&gt; &lt;code&gt;YOUR_API_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Get the the doc ID from your Coda doc by copying and pasting all the characters after the &lt;code&gt;_d&lt;/code&gt; in the URL of your Coda doc (should be about 10 characters). You can also use the &lt;em&gt;Doc ID Extractor&lt;/em&gt; tool in the &lt;a href="https://coda.io/developers/apis/v1beta1#section/Using-the-API/Resource-IDs-and-Links"&gt;Coda API docs&lt;/a&gt;. Copy and paste your doc ID into &lt;code&gt;YOUR_SOURCE_DOC_ID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Go back to your &lt;a href="https://coda.io/account"&gt;account settings&lt;/a&gt; and scroll down to the very bottom until you see “Labs.” Toggle “Enable Developer Mode” to ON.&lt;/li&gt;
&lt;li&gt;Hover over the table name in your Coda doc and click on the 3 dots that show up next to your table name. Click on “Copy table ID” and paste this value into &lt;code&gt;YOUR_SOURCE_TABLE_ID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To get your Google Sheets ID, get all the characters after &lt;code&gt;/d/&lt;/code&gt; in your Google Sheets file up until the slash and paste this into &lt;code&gt;YOUR_GOOGLE_SHEETS_ID&lt;/code&gt;. See &lt;a href="https://stackoverflow.com/a/36062068/1110697"&gt;this link&lt;/a&gt; for more info.&lt;/li&gt;
&lt;li&gt;Write in the name of the worksheet from your Google Sheets file where data will be synced into in the &lt;code&gt;YOUR_GOOGLE_SHEETS_WORKSHEET_NAME&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;In Google Sheets, create a new column name at the end of your column headers called something like &lt;code&gt;Coda Source Row URL&lt;/code&gt; and make sure there is no data in that column below the header. Write that column name in &lt;code&gt;YOUR_SOURCE_ROW_URL_COLUMN_NAME&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Go back to Google Apps Script, click on the Select function dropdown in the toolbar, and select &lt;code&gt;runSync&lt;/code&gt;. Then click the play ▶️ button to the left of the bug 🐞 button. This should copy over all the data from your Coda doc to Google Sheets.&lt;/li&gt;
&lt;li&gt;To get the script to run every minute, hour, or day, click on the clock 🕒 button to the left of the ▶️ button to create a &lt;a href="https://developers.google.com/apps-script/guides/triggers/installable#time-driven_triggers"&gt;time-driven trigger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Click Add Trigger, make sure runSync is set as the function to run, “Select event source” should be &lt;code&gt;Time-driven&lt;/code&gt;, and play around with the type of time based trigger that fits your needs. I like to set the “Failure notification settings” to &lt;code&gt;Notify me immediately&lt;/code&gt; so I know when my script fails to run.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setup: Google Sheets to Coda script
&lt;/h2&gt;

&lt;p&gt;Most of the steps above apply to the &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js"&gt;sheets_to_coda.js&lt;/a&gt; script as well but there are few extra features.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can follow steps 1–10 above to fill out &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js#L12"&gt;line 12&lt;/a&gt; to &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js#L18"&gt;line 18&lt;/a&gt; in the script (except &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js#L14"&gt;line 14&lt;/a&gt; mentioned in the next step). The main difference is that “SOURCE” and “TARGET” are flipped around since you are now syncing from a &lt;em&gt;source&lt;/em&gt; Google Sheet to a &lt;em&gt;target&lt;/em&gt; Coda doc.&lt;/li&gt;
&lt;li&gt;Your Coda table &lt;em&gt;cannot&lt;/em&gt; have a column named &lt;code&gt;Coda Row ID&lt;/code&gt;. If you need to use a column with this name, replace the &lt;code&gt;TARGET_ROW_ID_COLUMN&lt;/code&gt; variable with another value.&lt;/li&gt;
&lt;li&gt;If you have &lt;em&gt;edit access&lt;/em&gt; to the Google Sheet, follow step 11 above and write in the column name in &lt;code&gt;YOUR_SOURCE_ROW_URL_COLUMN_NAME&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you want the ability to add rows to your Coda table and NOT have these rows deleted every time the sync runs, create a column in your Coda table and name it &lt;code&gt;Do not delete&lt;/code&gt;. This column should be a checkbox column format and you will check the box for every row you manually add to your Coda table that you want to keep in that table. Otherwise, the script will delete that row and always keep the Coda table a direct copy of what’s in your Google Sheets file. If you change the name of this &lt;code&gt;Do not delete&lt;/code&gt; column, you must edit the value of the &lt;code&gt;DO_NOT_DELETE_COLUMN&lt;/code&gt; variable in &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js#L22"&gt;line 22&lt;/a&gt; of the script as well.&lt;/li&gt;
&lt;li&gt;If you want the script to completely delete and re-write the rows in your Coda table each time the script runs, set the &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js#L23"&gt;line 23&lt;/a&gt;. This may make the script run faster, but may not be faster for larger tables (few thousand rows). For Google Sheets files where you only have &lt;em&gt;view-only access&lt;/em&gt;, this setting will automatically get set to &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Follow steps 12–14 &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir"&gt;above&lt;/a&gt; to set up your time-driven trigger.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Use cases with Google Sheets
&lt;/h2&gt;

&lt;p&gt;Some of the most common use cases for integrating your application with Google Sheets can be found in the &lt;a href="https://gsuite.google.com/marketplace/category/works-with-spreadsheet"&gt;G Suite Marketplace&lt;/a&gt; for Google Sheets. From a business perspective, being able to visualize your data in Google Sheets allows you to slice and dice your data in ways you cannot do in on platform like Salesforce, for instance (FYI there’s a Salesforce &lt;a href="https://support.google.com/docs/answer/9073952?co=GENIE.Platform%3DDesktop&amp;amp;hl=en"&gt;add-on&lt;/a&gt; for Google Sheets).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bdgXo9MF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/530/0%2AzTAxg1i5hOBqEDrD" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bdgXo9MF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/530/0%2AzTAxg1i5hOBqEDrD" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The opposite is true too. Your team or company’s data may be stored in a Google Sheet but the data just sits there without being “actionable.” Let’s say you have a bunch of customer information and you want to create mailing labels with your customers’ names and addresses. Being able to “export” your data from Google Sheets into a mail merge application like Avery will make it easy to create the mailing labels you need.&lt;/p&gt;

&lt;p&gt;Then there’s the pinnacle of productivity in Google Sheets: &lt;em&gt;keeping data synced between your application and Google Sheets at all times&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When Google Sheets first came out, it was a game-changer since changes you make on your browser are instantly reflected in your colleague’s file. We have come to expect this with tools we use in the browser. But having data synced between Google Sheets and your other applications at all times is less common, and this is why the &lt;a href="https://developers.google.com/sheets/api"&gt;Google Sheets API&lt;/a&gt; is so important. From a Coda perspective, there are several use cases you might want to keep your Coda doc synced with a Google Sheet (and vice versa):&lt;/p&gt;

&lt;h3&gt;
  
  
  Data synced from your Google Sheet
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HR &amp;amp; recruiting&lt;/strong&gt;  — All your candidates are stored in a Google Sheet but you want to be able to move candidates through different stages in the interviewing pipeline and Google Sheets isn’t sufficient for your needs. Having all your candidates in a table in Coda means you can use templates like &lt;a href="https://coda.io/@evanatcoda/coordinating-candidates"&gt;this one&lt;/a&gt; to manage candidates more effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce and ERP&lt;/strong&gt;  — Orders, customers, and POs may all be different tabs in a Google Sheet that gets updated through Shopify or some other e-commerce platform. In order to &lt;em&gt;manage&lt;/em&gt; your e-commerce business, you may want to see charts, calendar of shipments, and reports that Google Sheets cannot provide easily. Syncing the data from Google Sheets to Coda means you can do ERP properly (see &lt;a href="https://coda.io/@wilson-silva/mini-e-commerce-erp"&gt;this template&lt;/a&gt; as an example).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Feedback&lt;/strong&gt;  — You may have a ticketing system like Zendesk or Intercom and all feedback lands in a Google Sheet somewhere. You can do some basic analytics in the Google Sheet but to &lt;em&gt;reply&lt;/em&gt; to the feedback means you have to go into Gmail and start replying to customers. If your customer feedback is all in a Coda doc, you can run analytics &lt;em&gt;and&lt;/em&gt; send emails using the &lt;a href="https://coda.io/packs/gmail"&gt;Gmail Pack&lt;/a&gt; (see &lt;a href="https://coda.io/@hales/customer-feedback-hub"&gt;this template&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data synced to your Google Sheet
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3rd-party vendor reporting&lt;/strong&gt;  — Your vendors may not be using Coda yet, but you have all your vendor data in Coda and need to send them the data in a format they prefer. While you could &lt;a href="https://help.coda.io/en/articles/3727616-intro-to-publishing"&gt;publish your Coda doc&lt;/a&gt;, the vendor still wants the data in a Google Sheet you have edit access to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data “backup”&lt;/strong&gt;  — Your team may create thousands of rows of data every quarter in a Coda doc and want to start each quarter “fresh.” Coda docs grow with your teams and they may get slow as you add in more functionality, so having a backup of your data in Google Sheets is another reason to sync data from your Coda doc to Google Sheets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finance &amp;amp; Accounting&lt;/strong&gt;  — Most internal finance and accounting functions still use Excel and spreadsheets for month-end reporting, taxes, and other business-critical activities. As your data grows in Coda, you can keep your finance counterparts in the loop by having your data synced to a Google Sheet which your finance team can use for their reporting and forecasting purposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up Google Apps Scripts
&lt;/h2&gt;

&lt;p&gt;Before you start using the scripts to sync data from Coda to Google Sheets or vice versa, you need to have Google Apps Script setup correctly. Just navigate to &lt;a href="http://script.google.com"&gt;script.google.com&lt;/a&gt; and click on &lt;strong&gt;New Project&lt;/strong&gt;. You’ll land in the GAS script editor. At this point, click on &lt;strong&gt;Resources→Libraries&lt;/strong&gt; in the toolbar and you’ll want to paste in the following Coda library for Google Apps Script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15IQuWOk8MqT50FDWomh57UqWGH23gjsWVWYFms3ton6L-UHmefYHS9Vl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After you add the library, you can pick a version of the library to use (I just picked the latest version to take advantage of all the latest features in Coda’s API):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X_G93uy6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/802/0%2Aaquaa4jlWyyqtmP0" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X_G93uy6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/802/0%2Aaquaa4jlWyyqtmP0" alt=""&gt;&lt;/a&gt;&lt;em&gt;Add Coda’s library for Google Apps Script&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Syncing a Coda doc to Google Sheets
&lt;/h2&gt;

&lt;p&gt;Setting up the script for syncing a table from a Coda doc to a Google Sheets requires a few simple inputs. I walk through how to get some of these inputs in my &lt;a href="https://coda.io/@atc/how-to-sync-data-between-coda-docs-and-google-sheets-using-googl"&gt;previous tutorial&lt;/a&gt;, so read that if you have any questions on how to get the following inputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coda doc ID:&lt;/strong&gt; This is the string of characters after the &lt;code&gt;_d&lt;/code&gt; in the URL of your Coda doc&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coda table ID:&lt;/strong&gt; The unique ID for the table you want to sync from in Coda. If you have &lt;em&gt;Enable Developer Mode&lt;/em&gt; turned on in your account settings, you can get the table ID by simply clicking the 3 dots next to your table:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WYxpJoWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/474/0%2A97biLRrR-KilFujj" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WYxpJoWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/474/0%2A97biLRrR-KilFujj" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheet ID&lt;/strong&gt;  — This is the string of characters after the &lt;code&gt;/d&lt;/code&gt; in the URL of your Google Sheet (see &lt;a href="https://developers.google.com/sheets/api/guides/concepts#spreadsheet_id"&gt;documentation here&lt;/a&gt; on how to get this ID).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheet worksheet name&lt;/strong&gt;  — Name of the individual worksheet in your Google Sheet you want to sync data &lt;em&gt;into&lt;/em&gt; from your Coda doc&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source Row Column&lt;/strong&gt;  — This is the only customization you’ll have to do to your Google Sheet. You’ll need to add a column (typically the last column in your Google Sheet) that’s called something like &lt;code&gt;Coda Source Row URL&lt;/code&gt;. This is the name used in the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;script&lt;/a&gt;. This is an &lt;strong&gt;important&lt;/strong&gt; column to have in your Google Sheet since it will store the unique URL to a row in your Coda table. More about this later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have these inputs, you’re ready to get started with syncing your data!&lt;/p&gt;

&lt;h3&gt;
  
  
  Column names in Google Sheets
&lt;/h3&gt;

&lt;p&gt;Try to keep the name of the columns in your Google Sheet the same as the columns in your Coda table. All the columns you want to sync from your Coda table to the Google Sheet should have its own column.&lt;/p&gt;

&lt;p&gt;The one exception is the &lt;code&gt;TARGET_SHEET_SOURCE_ROW_COLUMN&lt;/code&gt; variable which you’ll see in the script. Whatever value you put in this variable should also be the name of the column in your Google Sheet. You should put this column at the end of your table in Google Sheets like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ep_ijLCh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/626/0%2Ad1_4Kqf16DB26Kls" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ep_ijLCh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/626/0%2Ad1_4Kqf16DB26Kls" alt=""&gt;&lt;/a&gt;&lt;em&gt;Source row column to put in your Google Sheet&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This column will be overwritten by the Google Script with the unique source row URL from Coda (every row in a Coda table has a unique identifier). The reason why we need this column for the source row URL is so that the script knows which rows have been added to the Google Sheet so that if you delete any rows in the &lt;em&gt;source&lt;/em&gt; Coda doc, those rows can be deleted in the &lt;em&gt;target&lt;/em&gt; Google Sheet. This brings me to a quick aside about the benefits of these source row URLs (these are called &lt;code&gt;browserLink&lt;/code&gt;s in the &lt;a href="https://coda.io/developers/apis/v1beta1"&gt;API&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  A unique row identifier
&lt;/h3&gt;

&lt;p&gt;If you are a heavy user of Google Sheets, you may find yourself creating a “unique ID” column in table so that when you reference that row somewhere else in your Google Sheet, you can do a &lt;code&gt;VLOOKUP&lt;/code&gt; to pull all the data related to that row. Sometimes you can get away with a column of data (maybe it’s a customer name, task name, or project name). For instance, in this screenshot the unique ID is the &lt;code&gt;StaffID&lt;/code&gt; column:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6lo3yTse--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/753/0%2Amk6vx6I3lXyFAWbo" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6lo3yTse--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/753/0%2Amk6vx6I3lXyFAWbo" alt=""&gt;&lt;/a&gt;&lt;em&gt;Unique ID column in Google Sheets&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To cover the cases where your table does not have a unique ID, the script puts the unique row URL from Coda into the &lt;code&gt;TARGET_SHEET_SOURCE_ROW_COLUMN&lt;/code&gt; to act as the unique identifier. The &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; script also utilizes this column (assuming you have edit access to the Google Sheet). In lieu of this unique ID column, there’s no way for the script to know which rows have been added to the Google Sheet from Coda since there’s &lt;em&gt;no native row ID system in Google Sheets&lt;/em&gt; (see &lt;a href="https://stackoverflow.com/questions/38114591/is-it-possible-to-access-row-id-of-a-google-spreadsheet"&gt;this thread&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Fabricating a unique ID in Google Sheets
&lt;/h3&gt;

&lt;p&gt;One alternative to fabricate this unique identifier in your data set is to concatenate a bunch of columns together in hopes that this new column will be the unique ID for that row:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wCvqTFZ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ApmEnLZpCjlYxMwsn" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wCvqTFZ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ApmEnLZpCjlYxMwsn" alt=""&gt;&lt;/a&gt;&lt;em&gt;Creating your own unique ID in Google Sheets&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the above screenshot, &lt;code&gt;Feature&lt;/code&gt; is actually a pretty unique column of data. But to be 100% sure, there’s a &lt;code&gt;Fabricated ID&lt;/code&gt; column which concatenates &lt;code&gt;Feature&lt;/code&gt;, &lt;code&gt;Team&lt;/code&gt;, and &lt;code&gt;Milestone&lt;/code&gt; to create a “more unique” ID in the event there are two &lt;code&gt;Features&lt;/code&gt; with the same name. This is not a perfect method due to two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The fabricated ID column might not be unique enough and it might be duplicated in other rows (which means you would have to concatenate more columns of data to fabricate that unique ID)&lt;/li&gt;
&lt;li&gt;The columns you have concatenated may change (in this case, the &lt;code&gt;Team&lt;/code&gt; or &lt;code&gt;Milestone&lt;/code&gt; may change which would ruin the uniqueness of the ID)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In a previous life as a financial analyst, I employed this fabricated ID trick quite often but I had to choose the columns wisely. Typically in a report that has a time series, this would involve picking a dimension (e.g. west region), metric (e.g. sales), and the date for that specific row. This worked for static reports where data wasn’t getting deleted or updated too often. It’s a lot more risky to utilize this strategy with a shared Google Sheet with your team where data is constantly changing. Choose your columns wisely if you go down this path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RqTGo4ZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/471/0%2An7qBiAsD7_s-VuIG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RqTGo4ZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/471/0%2An7qBiAsD7_s-VuIG" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mixing columns in Coda
&lt;/h3&gt;

&lt;p&gt;The advantages of having a unique identifier for the rows in Coda also applies to columns in Coda as well (this benefit is realized in the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; script). For syncing Coda to Google Sheets, the script &lt;em&gt;has&lt;/em&gt; to use the actual names of the columns in Google Sheets since there’s also no &lt;em&gt;native column ID in Google Sheets&lt;/em&gt;. This means if your column in Coda is named &lt;code&gt;Projects&lt;/code&gt; but you accidentally misspell the column name in Google Sheets to &lt;code&gt;Project&lt;/code&gt;, the data will not sync over correctly from Coda to Google Sheets.&lt;/p&gt;

&lt;p&gt;One feature of the script is that you can re-order the columns in Coda and the data will still sync over correctly based on the column names. So your tables in Coda and Google Sheets could be organized like this, and the sync would still work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HPrTkgiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A2Fa9ftC-aFZbGPEd" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HPrTkgiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A2Fa9ftC-aFZbGPEd" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sortCodaTableCols()&lt;/code&gt; &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js#L167"&gt;function&lt;/a&gt; re-arranges the columns in Coda to reflect the order of the columns in Google Sheets by simply looking for the column name in Coda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var headerCodaTable = sourceRows[0]['cells'].map(function(row) { return row['column'] });
  var sheetsColOrder = [];

  headerRow.map(function(col) {
    sheetsColOrder.push(headerCodaTable.indexOf(col))
  })

  var sortedSourceRows = sourceRows.map(function(row) {
    var cells = sheetsColOrder.map(function(col) {
      if (col == -1) {
        return {        
          column: null,
          value: null,
        }
      } 
      else {
        return {
          column: headerCodaTable[col], 
          value: row['cells'][col]['value'],
        }       
      }
    });
    return {cells: cells}
  })
  return sortedSourceRows;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This means you can have your own “custom” columns in Coda or Google Sheets which can even contain formulas, and they won’t corrupt the sync from &lt;code&gt;Task&lt;/code&gt;, &lt;code&gt;Team&lt;/code&gt;, and &lt;code&gt;Project&lt;/code&gt; to their respective columns in Google Sheets. As long as these custom column names in Coda or Google Sheets don’t show up in the other platform, then you can do whatever you want with these custom columns:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RRWSEGki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AV88Z7F8N8RFJ_2jq" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RRWSEGki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AV88Z7F8N8RFJ_2jq" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This could be useful if you work with a vendor who needs to see data in a Google Sheet to perform certain calculations that could be meaningful to them but don’t really matter to you and your Coda doc. As long as there isn’t a column name in the Google Sheet that matches the name of a column in your Coda table, then everything will work as intended.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding and deleting rows
&lt;/h3&gt;

&lt;p&gt;The main &lt;code&gt;runSync()&lt;/code&gt; function runs two other functions: &lt;code&gt;addDeleteToSheets()&lt;/code&gt; and &lt;code&gt;updateSheet()&lt;/code&gt;. The logic here is to &lt;em&gt;add&lt;/em&gt; any new rows from Coda to Google Sheets and &lt;em&gt;delete&lt;/em&gt; any rows from Google Sheets that were deleted from Coda. As mentioned &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir"&gt;above&lt;/a&gt;, the script uses a &lt;code&gt;TARGET_SHEET_SOURCE_ROW_COLUMN&lt;/code&gt; to keep track of all the unique rows that need to be synced from Coda to Google Sheets.&lt;/p&gt;

&lt;p&gt;An added benefit of using this “source row column” in Google Sheets is that you can add new rows of data to Google Sheets manually and leave the “source row column” blank. When the sync runs, the script essentially skips these new rows because they don’t have a URL that maps to an existing row in Coda. I’m not sure about the exact use case for when you would want to do this, but perhaps your Coda doc keeps track of sales from a store and your accounting team gets the data synced to a Google Sheet like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fu5-wr5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AUJYZlR8xrQDCFBNL" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fu5-wr5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AUJYZlR8xrQDCFBNL" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The columns in yellow are the ones that get synced from your Coda doc. The first 3 rows get synced correctly because you see values in the &lt;code&gt;Source Row URL&lt;/code&gt; column. The accounting team realizes that there are more sales that were not accounted for and don’t exist in your Coda doc. They might manually add rows 5 and 6 and have a column they use internally called &lt;code&gt;Manual Enter&lt;/code&gt; to keep track of the rows they are manually adding to the Google Sheet. When the sync runs next, rows 5 and 6 won’t get overwritten or deleted because they left the &lt;code&gt;Source Row URL&lt;/code&gt; column blank.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating rows
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;addDeleteToSheets()&lt;/code&gt; function was relatively simple to write, but &lt;code&gt;updateSheet()&lt;/code&gt; was much more difficult given that rows in Google Sheets might be sorted in all kinds of ways. Additionally, I felt that scanning the entire Google Sheet for a source row URL and then scanning each column value to see if an update is needed was inefficient. Even if you have only 100 rows in your Coda doc that you want to sync to Google Sheets, that means there could potentially be 10,000 comparisons just for the row URLs alone every time the sync runs.&lt;/p&gt;

&lt;p&gt;One option I considered was just blowing up the entire list of data in Google Sheets first (deleting all the rows) and re-writing the data from Coda to Google Sheets. This also didn’t feel right because for larger tables this could potentially hit Google Apps Script &lt;a href="https://developers.google.com/apps-script/guides/services/quotas"&gt;rate limits&lt;/a&gt; and would prevent the need for the &lt;code&gt;addDeleteToSheets()&lt;/code&gt; function, prevent the need for the “source row column” in Google Sheets, and wouldn’t allow the user to manually add rows to the Google Sheet because those rows would get wiped out on the sync.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZvtJDBpc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2A6GR_77Ms6rdGdvRZ" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZvtJDBpc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2A6GR_77Ms6rdGdvRZ" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My thinking was to create two 2-D tables that were sorted exactly the same. The first table contains the rows from Coda that also exist in Google Sheets. The second table contains the rows in Google Sheets. The tables would contain the same number of rows and columns so you could then do a sequential comparison between the source Coda table and the target Google Sheet and see if there are any updates that need to be made in the Google Sheet.&lt;/p&gt;

&lt;p&gt;The first thing to do was to convert the row objects in Coda to a 2-D table that is more similar to Google Sheets’ row objects. The &lt;code&gt;convertValues()&lt;/code&gt; &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js#L239"&gt;function&lt;/a&gt; “flattens” the Coda row object so that each row object simply contains an array of column values:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lvxO2hrI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Axhs_-oJfl0SUjoqWJ8eKWg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lvxO2hrI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Axhs_-oJfl0SUjoqWJ8eKWg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of the work in these scripts is actually just data munging so that the data is in format that is acceptable for Coda and Google Sheets. Once the tables are sorted in the same order in terms of rows and columns, the script can now check cell by cell if there are any chances that need to be synced over to Google Sheets.&lt;/p&gt;

&lt;p&gt;I felt this sequential comparison of cells between the Coda and Google Sheets table was more performant than scanning for each row URL. The number of comparisons between the source and target tables is limited to the number of “cells” in either table. In this example, the script would only have to make 15 comparisons before figuring out that there are three cells in Coda that have been updated and need to be synced over to Google Sheets:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C-JAWTFv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/580/0%2AnkAY0g7Eau1rdGvB" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C-JAWTFv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/580/0%2AnkAY0g7Eau1rdGvB" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this may seem like a performance boost, there is a lot of pre-processing to get the rows sorted correctly, so the net result might be same in terms of rows and cells scanned. There much more smarter people out there who understand sorting algorithms, so there may be an even more efficient approach here 🤷‍♂️.&lt;/p&gt;

&lt;h3&gt;
  
  
  A little helper sort function
&lt;/h3&gt;

&lt;p&gt;In order to get the tables sorted perfectly before doing the cell by cell comparison, I needed to figure out a way to sort an array of arrays by some value. In this case, we have a bunch of arrays of column values that represent our rows, and the unique ID we want to sort on is the source row URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rThBpnV4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/670/0%2ACeoxN0dXKQ6d2a3E" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rThBpnV4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/670/0%2ACeoxN0dXKQ6d2a3E" alt=""&gt;&lt;/a&gt;&lt;em&gt;How do we sort each row object by the 7th element (row URL)?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I created this little &lt;code&gt;sortArray()&lt;/code&gt; &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/coda_to_sheets.js#L239"&gt;function&lt;/a&gt; that’s one of the workhorses in the script. It seems like such a common problem and I was surprised there wasn’t a built in sort function to sort an array of arrays (or maybe I just didn’t search hard enough). So if I want to sort the &lt;code&gt;targetRows&lt;/code&gt; object below which contains all the rows in my Google Sheet, I run the &lt;code&gt;sort()&lt;/code&gt; function on it and pass in the &lt;code&gt;sortArray()&lt;/code&gt; function and the returned &lt;code&gt;sortedTargetRows&lt;/code&gt; object is…as you expected…sorted by the source row URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var sortedTargetRows = targetRows.**sort(sortArray)**;

function sortArray(a, b) {
  var x = a[rowURLIndex];
  var y = b[rowURLIndex];
  if (x === y) {
    return 0;
  }
  else {
    return (x &amp;lt; y) ? -1 : 1;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;One thing I learned about the &lt;code&gt;sort()&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort"&gt;function&lt;/a&gt; is that if you pass in what they call a &lt;code&gt;compareFunction&lt;/code&gt; (in my case the &lt;code&gt;sortArray()&lt;/code&gt; function), to sort values by alphabetical order, it actually sorts in alphabetical order for values with &lt;em&gt;uppercase&lt;/em&gt; letters followed by &lt;em&gt;lowercase&lt;/em&gt; letters. Here is a list of values and how you expect them to be sorted versus how the &lt;code&gt;sort()&lt;/code&gt; function actually sorts stuff:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FKh72bmc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/368/1%2AN_mFvNDMSGAZxAzgbxxmwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKh72bmc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/368/1%2AN_mFvNDMSGAZxAzgbxxmwA.png" alt=""&gt;&lt;/a&gt;&lt;em&gt;WTF?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now if you sort this list of values in a spreadsheet or Coda table, you’ll get the results in the &lt;code&gt;What you expect&lt;/code&gt; column. I couldn’t figure out why the sorted values didn’t match up with what I expected after sorting the values in Google Sheets. Then after some debugging I realized this is the default behavior of the &lt;code&gt;sort()&lt;/code&gt; function in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort"&gt;JavaScript&lt;/a&gt;. A common workaround is to apply the &lt;code&gt;toUpperCase()&lt;/code&gt; function to the value so that you are doing a case-insensitive sort. Unfortunately, this won’t work for the script because it’s possible for a table in Coda to have two row IDs with the same order of six characters but just be capitalized differently (e.g. a row ID of &lt;code&gt;NPmgrG&lt;/code&gt; and &lt;code&gt;NPMGRG&lt;/code&gt; could exist in the same table).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p6IhEWtL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/526/0%2AxnsS55bL1khGm9Do" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p6IhEWtL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/526/0%2AxnsS55bL1khGm9Do" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our case, we need to find a &lt;em&gt;case-sensitive&lt;/em&gt; sort to account for the uniqueness of row IDs. I searched for a function like this to no avail. Then I realized it doesn’t matter if the script doesn’t sort the table in the alphabetical order I expect as long as it applies the same “incorrect” sort to both the source and target tables &lt;em&gt;equally&lt;/em&gt;. This means both tables will still be sorted in the same order just not in the order we expect from a typical sort in Google Sheets or Excel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syncing Google Sheets to a Coda doc
&lt;/h2&gt;

&lt;p&gt;After writing the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script, I thought the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; script would be a breeze since I had written all the functions to convert and sort data. All I would have to do is just switch around some variables and everything would work out just fine. Turns out I was completely wrong since there are a bunch of edge cases to account for in Google Sheets that makes the sync a little more difficult compared to Coda to Google Sheets.&lt;/p&gt;

&lt;p&gt;You can follow most of the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir"&gt;steps&lt;/a&gt; in the Coda to Google Sheets setup to get the values you need for the script to run, but there are a few caveats and extra options you can set to get similar functionality as the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Target Row Id Column&lt;/strong&gt;  — This is a key that stores each row’s unique ID from a Coda table. This value is in the “source row URL” (last 6 characters). Be default this variable is set as “Coda Row ID,” so make sure you don’t have a column in your Coda table with this name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do Not Delete Column&lt;/strong&gt;  — Unlike Google Sheets, the script is not written in a way where you can add additional rows to the &lt;em&gt;target&lt;/em&gt; Coda table without having them deleted when the sync runs. As mentioned &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir"&gt;above&lt;/a&gt; for the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script, you can add rows to your &lt;em&gt;target&lt;/em&gt; Google Sheet and not have them deleted on the sync. You need to create a checkbox column in your Coda table called &lt;code&gt;Do not delete&lt;/code&gt; and check off the box for that row if you don’t want it to get deleted on the sync. If you prefer a different column name, just change the value for the &lt;code&gt;DO_NOT_DELETE_COLUMN&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rewrite Coda Table&lt;/strong&gt;  — Unlike the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script, you have the option to completely delete all the rows in your &lt;em&gt;target&lt;/em&gt; table and re-write them with all the rows from your &lt;em&gt;source&lt;/em&gt; Google Sheet. Set the &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; variable to true if you want this behavior (may result in a faster sync).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Column and row limitations
&lt;/h3&gt;

&lt;p&gt;If you have edit access to the Google Sheet, you will need to add a column at the end of your table called something like “Source Row URL” similar to the “Coda Source Row URL” pattern mentioned &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir"&gt;above&lt;/a&gt; for the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script. After writing the data from Google Sheets to Coda for the first time, the unique row URLs from Coda are copied over into this “Source Row URL” column in your editable Google Sheets. Obviously this doesn’t apply to Google Sheets where you only have read-only access (more on that later).&lt;/p&gt;

&lt;p&gt;One limitation of the script is that if you add a new column to the Google Sheet, you also need to add that same column name to the Coda table. It’s ok if the column &lt;em&gt;order&lt;/em&gt; isn’t the same in Coda, but that column name just needs to exist somewhere in the Coda table. You can just hide the column in Coda to make the table nice and clean. This is actually a limitation caused by the way I structured the script, so hopefully it doesn’t cause you too much inconvenience 😬.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OpBu26en--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/245/0%2A2uqYyCQU4uTcRy5A" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpBu26en--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/245/0%2A2uqYyCQU4uTcRy5A" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Be careful with empty rows in your data in Google Sheets because those rows also get “synced” over to Coda. Not only will those empty rows show up in your Coda table, they will get their own source URLs. Ideally, the Google Sheet won’t contain any empty rows and this won’t be a problem for you.&lt;/p&gt;

&lt;p&gt;A few other “small” things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Formulas don’t sync&lt;/strong&gt;  — Probably not a huge surprise as this is also a limitation of the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script. Any columns with formulas you sync over to Coda will just be hard-coded to that column in your Coda table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resetting column formats&lt;/strong&gt;  — When your Coda table is blank and you’re syncing over rows for the &lt;em&gt;first time&lt;/em&gt; from Google Sheets, you may have to change some of the column formats to the proper format. For instance, if your dates in Google Sheets are in &lt;a href="https://stackoverflow.com/questions/8405087/what-is-this-date-format-2011-08-12t201746-384z"&gt;Zulu format&lt;/a&gt;, Coda will sometimes interpret these values as a select list. After the sync, just change the column format in Coda to the Date format you want and future syncs will work just fine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can’t sort your Google Sheet&lt;/strong&gt;  — The script looks for empty source row URLs in the &lt;code&gt;SOURCE_SHEET_SOURCE_ROW_COLUMN&lt;/code&gt; in your Google Sheet and it scans that column until it finds an empty value to start pasting in new source row URLs from Coda. If you sort your table, that column will get all jumbled and the script will break. New rows that you add to the Google Sheet should have the source row URL column blank and these blank cells need to be contiguous.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting a timer for source row URLs
&lt;/h3&gt;

&lt;p&gt;You will notice that the data syncs over pretty quickly to Coda, but the &lt;code&gt;SOURCE_SHEET_SOURCE_ROW_COLUMN&lt;/code&gt; (aka the “source row URL”) takes a couple seconds to show up in your Google Sheet. The reason this happens is because of the steps that need to happen for this sync to work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the rows that need to be added from Google Sheets to Coda&lt;/li&gt;
&lt;li&gt;Insert those new rows into Coda&lt;/li&gt;
&lt;li&gt;Coda snapshots the new data added to your table&lt;/li&gt;
&lt;li&gt;Look to see if the source row URLs have shown up in the Coda table&lt;/li&gt;
&lt;li&gt;Copy over the source row URLs to Google Sheets once those URLs show up&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key step in #3 since that snapshot can take a few seconds to happen. If we try to copy the source row URLs right after the rows are inserted into the Coda table, the script will come up with nothing an no row URLs will show up in your Google Sheet.&lt;/p&gt;

&lt;p&gt;To get around this, I added a little sleep timer to basically check for the source row URLs every two seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while(currentCodaRows.length &amp;lt;= allRows['targetRows'].length) {
  timer += 2;
  if (timer == 60) { break; }
  Utilities.sleep(2000);
  currentCodaRows = retrieveRows();    
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;allRows[‘targetRows’]&lt;/code&gt; object contains all the rows in your Coda table when the script runs for the first time. Every two seconds, the loop retrieves the rows in the Coda table in hopes that the the number of &lt;code&gt;currentCodaRows&lt;/code&gt; has &lt;em&gt;exceeded&lt;/em&gt; the number of original rows when the script first ran. The loop also breaks after 30 seconds if, for some reason, the Coda API cannot retrieve all the number of current rows added to the table. So far it hasn’t taken more than five seconds for the URLs to show up, but this is on a small data set of a 5–10 rows being added each time I tested the script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OG-rx_u8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/500/0%2AzY-I7QE0DFkc_cHA" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OG-rx_u8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/500/0%2AzY-I7QE0DFkc_cHA" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This sure seems like a heck a lot of work just to added some new rows to a table in Coda. That’s why I put in a &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; &lt;a href="https://github.com/albertc44/coda-google-apps-script/blob/master/sheets_to_coda.js#L23"&gt;variable&lt;/a&gt; to override all this source row URLs business.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deleting and re-writing rows each time
&lt;/h3&gt;

&lt;p&gt;As discussed with &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_su8ir"&gt;updating rows&lt;/a&gt; in the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script, I wanted to avoid this pattern of syncing data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete all rows in the target&lt;/li&gt;
&lt;li&gt;Copy all the rows from the source&lt;/li&gt;
&lt;li&gt;Insert the copied rows into the blank target table&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It didn’t seem like the right solution especially for a large table of thousands of rows because if you’re only changing or adding a few rows, the script has to delete and re-add all these thousands of rows. The simplicity of this approach is tempting, nonetheless. Just like the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Coda-Google-Sheets_suhDq"&gt;Coda -&amp;gt; Google Sheets&lt;/a&gt; script, the she&lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; script is broken down into &lt;code&gt;addDeleteToCoda()&lt;/code&gt; and &lt;code&gt;updateCoda()&lt;/code&gt; functions. The former function adds and deletes rows while the latter updates any existing rows in Coda that may have changed in the source Google Sheet.&lt;/p&gt;

&lt;p&gt;Blowing up the Coda table each time the sync runs would prevent the need for individual functions that add, delete, and update because the nature of blowing something up is that you can re-build from scratch. I haven’t measured which option is more performant but my hunch is that for smaller tables of data, setting &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; may actually make the script run faster at the expense of not having the source URLs in your Google Sheet.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; option is actually important for Google Sheets files you only have &lt;em&gt;read-only access&lt;/em&gt; to. By default, you can’t write source row URLs to a Google Sheet you have view-access to, so there’s no point in using source row URLs to figure out which rows need to be added, deleted, and updated. &lt;strong&gt;Side note:&lt;/strong&gt; the script doesn’t work on Google Sheets that have been &lt;a href="https://support.google.com/docs/answer/183965?co=GENIE.Platform%3DDesktop&amp;amp;hl=en"&gt;published to the web&lt;/a&gt;. You’ll know the Google Sheet is published when the URL has a &lt;code&gt;2PACX&lt;/code&gt; in the URL like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GgVwEqH2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/423/0%2AQXdI8_xV0loWMQzp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GgVwEqH2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/423/0%2AQXdI8_xV0loWMQzp" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting permissions from Google Sheets
&lt;/h3&gt;

&lt;p&gt;Instead of having to remember if you need to switch the &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; variable to &lt;code&gt;true&lt;/code&gt; when you’re syncing from a read-only Google Sheet, I did a little hack to get the permissions you have on the Google Sheet by trying to add the logged in user (you) as an editor to the Google Sheet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function sheetsPermissions() {
  try {
    fromSpreadsheet.addEditor(Session.getActiveUser());
  } 
  catch (e) {
    REWRITE_CODA_TABLE = true; // If no access automatically rewrite Coda tables each sync
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you have &lt;em&gt;edit-access&lt;/em&gt; to the Google Sheet, nothing happens since you are already an editor. If there is an error, then that means you don’t have permissions to add yourself as an editor to the Google Sheet (which means you only have read-only access). Int this case, the &lt;code&gt;REWRITE_CODA_TABLE&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt; and the script goes on and blows up the Coda table and replaces it brand new with data from your Google Sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Caveats &amp;amp; Notes
&lt;/h2&gt;

&lt;p&gt;There are many other variables to consider before implementing these scripts into your daily business-critical processes, but I think the given feature set should get you 90% of the way there. Having said that, there are a few more things to think about and small limitations about the scripts in general I’ve discovered along the way. This is by no means an exhaustive list.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using simple triggers in Google Apps Script
&lt;/h3&gt;

&lt;p&gt;I thought that the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; script could take advantage of &lt;a href="https://developers.google.com/apps-script/guides/triggers"&gt;simple triggers&lt;/a&gt; to fire off the script. Basically you could have the script fire right when you make an edit to any cell, the moment the Google Sheet loads, etc. Unfortunately, there are a few &lt;a href="https://developers.google.com/apps-script/guides/triggers#restrictions"&gt;restrictions&lt;/a&gt; to using simple triggers, and it looks like the script has to be entirely contained in Google Sheets to utilize simple triggers. Additionally, I don’t think the script could keep up with the speed of edits if you are looking for near real-time syncing. Data would just get choked as the script waits for source row URLs to appear and data would start pouring into your Coda doc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Mjqd4yk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/498/0%2AoYx95VUI6JdXhQih" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Mjqd4yk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/498/0%2AoYx95VUI6JdXhQih" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate limits
&lt;/h3&gt;

&lt;p&gt;There are rate limits for &lt;a href="https://developers.google.com/apps-script/guides/services/quotas"&gt;Google Apps Script&lt;/a&gt; as well as &lt;a href="https://help.coda.io/en/articles/3370370-are-there-any-size-limitations-on-docs-accessible-via-the-api"&gt;Coda&lt;/a&gt;. I’ve tried syncing tables with 10,000 rows in both scripts (6 columns) and they both seem to work. I think in one test the &lt;a href="https://coda.io/d/How-to-sync-data-from-Coda-to-Google-Sheets-and-vice-versa-with-_dv4i9X8bdFe/Google-Sheets-Coda_suKcq"&gt;Google Sheets -&amp;gt; Coda&lt;/a&gt; sync resulted in some rows missing in the Coda table. For the first time you sync data over, I’d recommend just doing a regular copy and paste instead of relying on the sync to copy all the data over correctly. Most likely, subsequent additions and edits would be as large so the sync should run smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  V8 runtime
&lt;/h3&gt;

&lt;p&gt;If you have existing Google App Scripts, you may have noticed this fun error message at the top of your editor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x4Wd71CN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/526/0%2A8azmCw5nLtC0HoqX" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4Wd71CN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/526/0%2A8azmCw5nLtC0HoqX" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These scripts utilize the &lt;a href="https://developers.google.com/apps-script/guides/v8-runtime"&gt;V8 runtime&lt;/a&gt; which takes advantage of a bunch of modern JavaScript features. The only changes I needed to make to upgrade the scripts was changing the syntax for &lt;code&gt;for each&lt;/code&gt; &lt;a href="https://developers.google.com/apps-script/guides/v8-runtime/migration#avoid_for_eachvariable_in_object"&gt;loops&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Moving off Coda or Google Sheets to a dedicated database
&lt;/h3&gt;

&lt;p&gt;It’s tempting to use a Google Sheet or Coda doc as your de facto database. The interface is familiar, easy to edit and use, and it lives in your browser. The danger is when it feels &lt;em&gt;so convenient&lt;/em&gt; that you start putting thousands or hundreds of thousands of rows into your spreadsheet and maybe rely on Zapier or these Google Apps Scripts to sync data in and out of other applications you use every day to get work done.&lt;/p&gt;

&lt;p&gt;If the process isn’t business-critical and your team can put up with this annoying little thing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HT_OacJe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/265/0%2AXW_WhsnQ-wZYEzx-" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HT_OacJe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/265/0%2AXW_WhsnQ-wZYEzx-" alt=""&gt;&lt;/a&gt;&lt;em&gt;Source: Ben Collins&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;…then by all means continue doing what you’re doing and pass the Google Sheet to the next intern or analyst who has to put up with updating it in the future. I would consider migrating your data to a dedicated database platform (like &lt;a href="https://cloud.google.com/bigquery"&gt;Google BigQuery&lt;/a&gt;) which has a nice integration with Google Sheets. Lots more to say about this subject, but I’ll just leave it at that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not a programmer
&lt;/h2&gt;

&lt;p&gt;Most of this post is me pretending to know what I’m talking about. I’m not a programmer, and the scripts could probably be improved 10X by someone who actually knows what they’re doing and understands how algorithms work. There are unnecessary loops and bugs stamped all over the scripts so please proceed with caution ⛔️. If you happen to be someone who knows more about this stuff than me, consider &lt;a href="https://github.com/albertc44/coda-google-apps-script"&gt;contributing&lt;/a&gt; to the code. I just did the bare minimum to get something to work and hopefully these scripts will be sufficient to get you on you your merry way of not having to copy and paste between Coda and Google Sheets 🤙.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hv_DPMeZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/336/0%2AggC9Nz1uVloUf5fJ" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hv_DPMeZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/336/0%2AggC9Nz1uVloUf5fJ" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>googlesheets</category>
      <category>coda</category>
      <category>googleappsscript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>On mastering your tools</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Wed, 11 Mar 2020 17:24:59 +0000</pubDate>
      <link>https://dev.to/coda/on-mastering-your-tools-2fa6</link>
      <guid>https://dev.to/coda/on-mastering-your-tools-2fa6</guid>
      <description>&lt;p&gt;For some of us, work is moving bits and pixels from one side of your computer screen to another. Moving your mouse and plugging in your laptop might be the most physical task you do during the workday. No matter how you define work, you are participating in skilled labor — you have developed an asset that others find valuable.&lt;/p&gt;

&lt;p&gt;When I think of traditional examples of skilled labor, the blacksmith comes to mind — a man heating iron in a forge, pounding on iron with a hammer, and toiling away in his shop. Something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F520%2F0%2A34gpv_nrXGlvTeNf" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F520%2F0%2A34gpv_nrXGlvTeNf"&gt;&lt;/a&gt;&lt;em&gt;Source: Improvement Era, 1941&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp-ZmF7dQ.b0.n0.cdn.getcloudapp.com%2Fitems%2FQwu74O1L%2Fwoman-blacksmith-joe-sanna.jpg%3Fv%3D3829b3d1436d5bdb2309d355d75a45b9" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp-ZmF7dQ.b0.n0.cdn.getcloudapp.com%2Fitems%2FQwu74O1L%2Fwoman-blacksmith-joe-sanna.jpg%3Fv%3D3829b3d1436d5bdb2309d355d75a45b9"&gt;&lt;/a&gt;&lt;em&gt;Source: Joe Sanna&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Historically, blacksmiths held an important position in the village. People might go to them for a pedestrian project like fixing a small appliance. They might also get called upon to fix wagon wheels, create armor, and even weapons to be used by the military. A blacksmith’s knowledge of heating iron with carbon gave them the ability to turn a natural resource into any tool that was needed in the village. Naturally, the definition of the job could be extended to bladesmith, nailmaker, and even dentist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp-ZmF7dQ.b0.n0.cdn.getcloudapp.com%2Fitems%2Fd5u0Nm7X%2FIMG_3067.JPG%3Fv%3D145af071ecc4f553ad143b0f80126426" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp-ZmF7dQ.b0.n0.cdn.getcloudapp.com%2Fitems%2Fd5u0Nm7X%2FIMG_3067.JPG%3Fv%3D145af071ecc4f553ad143b0f80126426"&gt;&lt;/a&gt;&lt;em&gt;Codans as blacksmiths: We stepped away from building Coda docs one night and forged steel objects at &lt;a href="https://lawlessforge.com/" rel="noopener noreferrer"&gt;Lawless Forge&lt;/a&gt; in Seattle. &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Whatever project was thrown at the blacksmith, they found a way to produce the tool necessary and become masters of their craft — something I feel everyone should be empowered to do as they challenge the status quo of their own tools.&lt;/p&gt;
&lt;h3&gt;
  
  
  Once a toolmaker always a toolmaker
&lt;/h3&gt;

&lt;p&gt;Think about all the online tools and applications you use at work today. Email, internal real-time chat, video conference, project tracking; all these platforms have an &lt;em&gt;opinionated&lt;/em&gt; way of how you should get your work done. Have you ever asked yourself the question: why must we communicate or track projects the way the software dictates?&lt;/p&gt;

&lt;p&gt;I started asking myself this question early on in my career as a financial analyst. Spreadsheets were a means to an end. I took some numbers, move them around the cells, and bam! The work was done. My stakeholders and management had the numbers they needed, and I could move forward with analyzing another data set.&lt;/p&gt;

&lt;p&gt;As I wrote in &lt;a href="https://blog.coda.io/from-one-spreadsheet-nerd-to-another-c857d25f65d3" rel="noopener noreferrer"&gt;this post&lt;/a&gt;, the skills I learned from analyzing data in spreadsheets prepared me for a career of toolmaking.&lt;/p&gt;

&lt;p&gt;I started to question the process in which the work on my team gets done (which typically involved data in a spreadsheet). Instead of the spreadsheet being an opinionated tool for how I should analyze data, I had my &lt;em&gt;own vision&lt;/em&gt; for how the spreadsheet could be molded and fine-tuned for my team to work better. The spreadsheet became my iron.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F0%2A_VMSehOvJ7f_aYym" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F0%2A_VMSehOvJ7f_aYym"&gt;&lt;/a&gt;&lt;em&gt;Source: Western Maine Blacksmith Association&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Aside from wanting to help my team be more efficient and productive, I could never switch back to a state of accepting a spreadsheet with poorly structured data, incorrect formulas, and inconsistent formatting. Similar to a blacksmith refining his technique through trial and error, I discovered keyboard shortcuts would make me as a toolmaker more efficient in…well…making tools. The spreadsheet would be molded to fit the requirements of the project, and I would accept nothing less.&lt;/p&gt;
&lt;h3&gt;
  
  
  Makers as blacksmiths
&lt;/h3&gt;

&lt;p&gt;As a master of their tools, the blacksmith knows all the shortcuts to bypass the inefficiencies with building or creating their next project. Makers share many similar characteristics as blacksmiths. Software engineers, for example, are always thinking of the most efficient method of solving a problem.&lt;/p&gt;

&lt;p&gt;Clive Thompson discusses these characteristics at length in his book &lt;em&gt;Coders: The Making of a New Tribe and the Remaking of the World&lt;/em&gt;. In this &lt;a href="https://www.wired.com/story/coders-efficiency-is-beautiful/" rel="noopener noreferrer"&gt;Wired article&lt;/a&gt;, Thompson tells the story of a software engineer named Jason Ho who was helping his dad with creating a more efficient employee clocking time system for his dad’s business. Ho created a prototype in 3 days and eventually productized the tool and started generating $10,000 per month from his project. Thompson describes the reason coders have a passion for efficiency:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Removing the friction from a system is an aesthetic joy; coders’ eyes blaze when they talk about making something run faster or how they eliminated some bothersome human effort from a process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thompson’s book includes stories about engineers who may not be optimizing for a financial outcome when working on various projects. For blacksmiths, I’d argue just being able to &lt;em&gt;build&lt;/em&gt; the tool, knowing the tool works as intended, and helps others results in an “aesthetic joy.”&lt;/p&gt;

&lt;p&gt;One of my favorite stories about a maker-turned-blacksmith who saw an inefficiency with how Instagram influencers get compensated built a bot that would post beautiful pictures of NYC on Instagram:&lt;/p&gt;


&lt;div class="instagram-position"&gt;
  &lt;iframe id="instagram-liquid-tag" src="https://www.instagram.com/p/B6daO96B_GS/embed/captioned/"&gt;
  &lt;/iframe&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://www.buzzfeednews.com/article/katienotopoulos/automated-instagram-influencer-bot-free-meals" rel="noopener noreferrer"&gt;Chris Buetti&lt;/a&gt; wanted to get free lunches in NYC so he had his bot post eye-catching photos with captivating captions to get thousands of followers. He then automated the emails to restaurants saying that he would post about them on his Instagram account if they gave him a free meal. Buetti was a master of his tools, and used it to not only score free meals, but shed some commentary on the influencer ecosystem that has been generated by platforms such as Instagram.&lt;/p&gt;

&lt;h3&gt;
  
  
  You are a maker
&lt;/h3&gt;

&lt;p&gt;My own maker experience is far from unique — Buetti’s own experience shows that the barrier to being a creator in today’s digital landscape is very low. The rise of “maker” communities ranges from YouTube creators on one end of the spectrum to engineers releasing cutting-edge open-source technologies on the other. This TED@MotorCity talk by Dale Dougherty of MAKE magazine gives a nice overview of the “&lt;a href="https://en.wikipedia.org/wiki/Maker_culture" rel="noopener noreferrer"&gt;maker movement&lt;/a&gt;,” which has evolved to include people building digital products.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mlrB6npbwVQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Your perception of a maker might be someone who is good with building with their hands or likes tinkering with electronics, but I believe the definition of a maker stretches way beyond that. You may not identify as a maker today, but chances are you have already “made” something in the past month. For example, if you have created YouTube video, taken a recipe and changed it a bit to fit your tastes, or invented a new workout routine at the gym, I would argue you are a maker. There is a lot of creativity that goes into creating engaging online content, and understanding the algorithms behind platforms like YouTube require patience, testing, and experimentation.&lt;/p&gt;

&lt;p&gt;For example, think about &lt;a href="https://www.blogilates.com/about-cassey/" rel="noopener noreferrer"&gt;Cassey Ho&lt;/a&gt;, creator of Blogilates, the #1 female fitness channel on YouTube with over 500 million video views and 4 million subscribers. &lt;/p&gt;

&lt;p&gt;As a fitness instructor, she deeply understood the barriers people face to exercise and decided to challenge the status quo of the traditional pilates class. By combining fun music and innovative choreography, Cassey created an entirely new genre of exercise: Pop Pilates. Through her dedication to her craft, she shaped the fitness industry and paved the way for YouTube creators to come. &lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/8Ox3KMmHxPM"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Or consider one of my favorite TV shows growing up--&lt;em&gt;MythBusters&lt;/em&gt; with Adam Savage and Jamie Hyneman. Adam and Jamie would spend the whole show creating some contraption to test a hypothesis and potentially dispel a myth. What I loved the most about the show was that these contraptions were sometimes way over the top and Adam and Jamie probably could’ve tested their hypothesis with a highly controlled experiment in a lab. As the duo are building their contraption, you could feel the excitement and joy during their process of imagining and building their creations even though the final test may only last a few seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F900%2F0%2AmETOwNcAFnRnqxCa" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F900%2F0%2AmETOwNcAFnRnqxCa"&gt;&lt;/a&gt;&lt;em&gt;Source: Business Insider&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The key takeaway from the show that applies to this story is that becoming a maker doesn’t mean you have to be driven by profit, fame, or views. What Dale and and &lt;em&gt;MythBusters&lt;/em&gt; teaches us is that you can be a maker by just being curious about the world around you and the tools you use. During a 2012 Maker Faire talk, Adam sheds some light on his journey becoming a maker:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It doesn’t matter what you make. And it doesn’t matter why. The importance is that you are making something. When you are making, the process you’re going through, the problem solving, the shaping your future with your hands, it’s inherently a good and positive conversation. It makes you into a critical thinker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Be the master of your craft
&lt;/h3&gt;

&lt;p&gt;In &lt;em&gt;Hammer’s Blow&lt;/em&gt;, one of the journals produced by The Artist-Blacksmith’s Association of North America, you’ll typically find tutorials and diagrams on how to build certain tools and crafts. The content is not too dissimilar from a video tutorial you might find today of some digital cloud platform. The author of one of the issues pays homage to and reminisces on a conversation with Francis Whitaker, a famous blacksmith who passed away in 1999:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F415%2F0%2AIspw6gGBBno6J50_" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F415%2F0%2AIspw6gGBBno6J50_"&gt;&lt;/a&gt;&lt;em&gt;Hammer’s Blow, 2000&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You’re the blacksmith…you are the expert on ironwork. You must do the highest standard of work possible, then use that work to teach your clients of the possibilities of hand forged iron. Through the work you will find the clients who value it. — Francis Whitaker&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By becoming a master of ironwork, Whitaker was able to create pieces that his clients didn’t even think were possible. He teaches us that knowing a tool inside and out not only makes you an expert on that tool, but gives you satisfaction in knowing you are getting closer to perfecting a craft.&lt;/p&gt;

&lt;p&gt;I think the values of the Artist-Blacksmith’s Association can crossover to so many other industries. Especially if you are in an industry that is averse to change and generally doesn’t adopt new methods or ways of doing things. The Artist-Blacksmith’s Association shows us that we can all be makers and change the course of our careers and industries. This quote from the Artist-Blacksmith’s Association of North America’s mission statement is illuminating:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With hammer and anvil, we will forge for mankind a richer life. We will preserve a meaningful bond with the past. We will serve the needs of the present, and we will forge a bridge to the future. Function and creativity is our purpose. Our task is great and so is our joy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the traditional blacksmith only had an anvil, hammer, and iron at their disposal, today’s digital maker has hundreds of SaaS tools, design tools, and APIs to build unique tools that traditionally would take a large development team to build. Instead being a master of one “tool” like the spreadsheet, these makers are masters of &lt;em&gt;integrating tools&lt;/em&gt;ーbeing able to connect disparate tools together to build something greater than the sum of its parts.&lt;/p&gt;

&lt;p&gt;Like Whitaker said, we should all pursue the highest standard work possible, shining a spotlight on ideas others have never seen before. In order to do this, we can no longer be &lt;em&gt;complacent&lt;/em&gt; with the tools we are given. As we acknowledge ourselves as makers, we should feel empowered to become masters of our crafts and challenge the status quo of the tools we use.&lt;/p&gt;




</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>programming</category>
      <category>motivation</category>
    </item>
    <item>
      <title>5 Ways to Succeed As A New Remote Worker</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Mon, 13 Jan 2020 20:48:39 +0000</pubDate>
      <link>https://dev.to/coda/5-ways-to-succeed-as-a-new-remote-worker-2ana</link>
      <guid>https://dev.to/coda/5-ways-to-succeed-as-a-new-remote-worker-2ana</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on the &lt;a href="https://remote-how.com/5-ways-to-succeed-as-a-remote-worker/"&gt;Remote-how&lt;/a&gt; blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Prior to joining &lt;a href="http://www.coda.io/"&gt;Coda&lt;/a&gt;, I had never worked remotely for a company.&lt;/p&gt;

&lt;p&gt;In my previous role, I would work from home every now and then, but for the most part I was expected to show up to the office, attend meetings I didn’t really want to attend, and then get work done at my desk. I had the opportunity to freelance and work on my own projects, and with that came the responsibility of setting my own hours and getting work done. For most independent consultants and freelancers out there, you are working remotely but don’t have a bigger team to answer to (unless you are working on-site for a specific client).&lt;/p&gt;

&lt;p&gt;Being a freelancer taught me a lot about routines, discipline, and knowing how to structure my days, weeks, and months. It didn’t teach me how to work with a broader team that is collocated in a different city. I want to share 5 tips on how to be successful when joining a company as a remote worker for the first time in your career.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Visit the team in person often
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xdo08dUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/airplane.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xdo08dUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/airplane.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
Nothing beats meeting your team in person and building real relationships. When I first started, I tried to visit our offices on the west coast as often as I could (I’m based in NYC). My first day was actually at an internal hackathon where the entire team gets together and works on brand new ideas that may eventually get built into the Coda platform. During the hackathon, I had a chance to meet almost everyone on the team in a somewhat stressful environment (true to the spirit of hackathons, we work on ideas for 2-3 days straight). During those few days, I got a chance to meet and work with my new teammates so that they could understand my working style.&lt;/p&gt;

&lt;p&gt;Every month or so, I would fly back for company events or just to work alongside my team. When you’re a new remote worker and don’t make an effort to meet your team in person, your teammates will only know you through Slack and on video conference calls. Taking the time to build relationships with your team members up will engender more trust and productivity down the road.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Be vocal through documentation
&lt;/h2&gt;

&lt;p&gt;All remote workers don’t have the opportunity to have “water cooler” conversations that their collocated colleagues have. These informal conversations can create clarity for a business issue and creates more collaboration between team members. Since you can’t regularly have these hallway conversations, you have to be a little more vocal through digital means. This means e-mail, Slack, and for me, Coda. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ZAqTwY8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/Coda.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ZAqTwY8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/Coda.gif" alt=""&gt;&lt;/a&gt;&lt;br&gt;
Aside from leaving feedback via Slack and e-mail, I use Coda heavily to upvote/downvote questions I have about projects, document the status of projects, and more. The various company-wide Coda docs we have set up allows for transparent sharing of company information and gives anyone in the company to voice their opinions and feedback. I use our various Coda docs in real time during meetings so that the meeting leader can see any questions or feedback I’m typing in as the meeting progresses.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Get a high quality webcam and mic
&lt;/h2&gt;

&lt;p&gt;This is a logistical aspect of being a new remote worker but many people decide to put convenience over quality. It’s easy to the headphones you already use with your iPhone or Android phone into your laptop and start getting on Zoom calls. On the other side where your entire team is watching and listening, the quality can come out really bad. You don’t want to be the one person on all Zoom calls where the audio and video quality is bad and people just want you to mute your mic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M-S-NhPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/image-4-copy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M-S-NhPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/image-4-copy.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
One of my favorite podcasters is &lt;a href="https://twitter.com/Jason?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor"&gt;Jason Calacanis&lt;/a&gt; and he has some very strict rules for his team on how to handle video conferences. If someone on his team is dialing in remotely, he requires them to have a headset with a stick mic, a webcam that gets plugged into their computer, and have a wired Ethernet connection. All these precautions help ensure good video and audio quality. You can get $20 headsets on Amazon that have amazing audio quality. I’ve been using &lt;a href="https://www.amazon.com/Mpow-All-Platform-Microphone-Noise-Canceling-Comfort-fit/dp/B07T4HVZ9N/ref=sxin_3_osp126-fe967965_cov"&gt;this one&lt;/a&gt; for the last 2 years and it works perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Join IRL communities
&lt;/h2&gt;

&lt;p&gt;Related to tip #2, you won’t have the opportunity for in-person lunches or happy hours that often with your team. Instead, I’ve opted to join in-person communities in my city to get that social interaction that comes with being a part of a team. For instance, at my co-working space (WeWork), I started going to events and meeting people that work near me to have some “work friends” even though they are not a part of my company. I created &lt;a href="https://coda.io/d/Coda-Maker-Meetups_dUxW7tPAUmS/Coda-NYC-January-2020-Meetup_su9Ji#_lu9V6"&gt;a meetup&lt;/a&gt; for Coda users in NYC and it’s helped me 1) meet others who have similar interests and 2) educate people about Coda.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I9dVLh4k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/1_FfaZuKLtKpjmIsSGJuR1sw-1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I9dVLh4k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://remote-how.com/wp-content/uploads/2020/01/1_FfaZuKLtKpjmIsSGJuR1sw-1.jpeg" alt=""&gt;&lt;/a&gt;&lt;br&gt;
In addition to starting your own community or meetup, make it a point to join other meetups with other like-minded people. There are most likely many remote work meetups where people who are new to remote work can discuss strategies for succeeding as a remote worker (including the tips from this article!).&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Set boundaries for work and personal life
&lt;/h2&gt;

&lt;p&gt;A common theme that comes up again and again in the remote work world is mental health. When you’re working in an office, everyone checks out at a certain time of the night and activity on Slack and e-mail slowly die down. As a new remote worker, you may be working in a new timezone, and may be adjusting to the new meeting times that don’t fit within a traditional 9-to-5. It’s really important to set boundaries for when work begins and ends for you because of the flexibility remote work gives you.&lt;/p&gt;

&lt;p&gt;This is especially true if you don’t have a co-working space or separate office, and you work from home. If it’s getting close to dinner time and you’re still working, what’s preventing you from ordering takeout and just eating at your desk? The barrier to doing this is super low and before you know it, you’re working right up until you go to sleep. Avoid the burnout that many remote workers face when they don’t have a grasp on the number of projects they can take on. Your mental and physical health should be your number one priority!&lt;/p&gt;

&lt;p&gt;Hopefully these tips will help you succeed as a new remote worker. If you have any questions or comments, feel free to leave them below!&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>remotework</category>
    </item>
    <item>
      <title>Simpler, cleaner, faster. Coda 2.0 is ready for your team.</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Thu, 24 Oct 2019 14:06:58 +0000</pubDate>
      <link>https://dev.to/coda/simpler-cleaner-faster-coda-2-0-is-ready-for-your-team-53og</link>
      <guid>https://dev.to/coda/simpler-cleaner-faster-coda-2-0-is-ready-for-your-team-53og</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally &lt;a href="https://blog.coda.io/introducing-coda-2dot0-34f19133b33e"&gt;posted&lt;/a&gt; on the Coda blog by Shishir Mehrotra&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Back in February, we launched &lt;a href="https://blog.coda.io/introducing-coda-1-0-88a484851ea9"&gt;Coda 1.0 with mobile&lt;/a&gt;. We said that makers now had all the basic building blocks needed to create docs as powerful as apps.&lt;/p&gt;

&lt;p&gt;Since then, we’ve been watching tens of thousands of makers build unique, surprising docs. Team leaders from Square to the New York Times made docs to scale their operations. The Figma Product Team envisioned and executed designs in Coda. Zapier built docs to create a more inclusive, interactive meeting culture. And people whose perspectives I’ve long admired, like &lt;a href="https://coda.io/t/Measure-What-Matters-OKR-Starter-Kit-by-John-Doerr_t3Ucruf9p0B"&gt;Measure What Matters author John Doerr&lt;/a&gt; and &lt;a href="https://coda.io/t/Dess-Prioritised-Productivity-Guide_tOGPVy4lYr6"&gt;Intercom co-founder Des Traynor&lt;/a&gt;, adapted their career insights and personal philosophies into docs.&lt;/p&gt;

&lt;p&gt;At the same time, we’ve been listening closely to your feedback, gleaned over thousands of community posts, meet-ups, doc builds, support chats, and dinner conversations. From this we converged on a clear answer for where we should focus next: “teams.” A small word, containing a universe of complexity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_AaJzZyU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cl.ly/109c7e0c114e/1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_AaJzZyU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cl.ly/109c7e0c114e/1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Based on aggregated data, these snapshots show team doc usage over a one-week period.



&lt;p&gt;We call these “galaxy charts”ーsnapshots of a week-in-the-life of a team and their docs. It’s not surprising that teams use docs in ways that are as wide-ranging and diverse as the teams themselves; collaboration in Coda takes many forms. For example, a fully distributed tech team that runs meetings in Coda is a much different constellation than a teacher distributing lecture materials.&lt;/p&gt;

&lt;p&gt;Today, I’m excited to introduce Coda 2.0, a simpler, cleaner, and faster doc for teams. It comprises new paid plans and a set of building blocks that address all the different galaxies of team collaboration.&lt;/p&gt;

&lt;p&gt;Coda 1.0 was for makers. Coda 2.0 is for the whole team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Coda 2.0
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A simpler, cleaner, faster experience for everyone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may love how powerful building in Coda is, but your teammates just want to work and jump in and out of docs. We simplified their most common interactions into &lt;strong&gt;easy filters&lt;/strong&gt; and conditional formats. No formulas required.&lt;/p&gt;

&lt;p&gt;Even better, we turned our favorite building block compositions into &lt;strong&gt;drag-and-drop templates&lt;/strong&gt;, and made them available right inside your doc. Now a teammate can add a topic voting table faster than you can say “show of hands.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jNJVgfwQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cl.ly/8993c1e6495f/2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jNJVgfwQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cl.ly/8993c1e6495f/2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We wanted to make Coda a more inviting and beautiful place to work. The &lt;strong&gt;visual refresh&lt;/strong&gt; technically started back in July when we released a fresh new canvasーwith fewer shadows and more space to think and plan. And it continues today with centering for readability and section headers to frame information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7PxqUaAl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cl.ly/d29fdd59c4f3/intro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7PxqUaAl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cl.ly/d29fdd59c4f3/intro.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The surface is also faster and more responsive, thanks to a ton of &lt;strong&gt;&lt;a href="https://medium.com/@preetangad/d96236669011"&gt;performance improvements&lt;/a&gt;&lt;/strong&gt;. You’ll notice scrolling, calculations, searching, and section-switching are all smoother and faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving teams the space they need.
&lt;/h2&gt;

&lt;p&gt;We saw a lot of makers and teams quickly outgrow their doc lists. With dozens of docs, shared among different teams, it became hard to organize all their Coda docs in a simple list. Today we’re launching &lt;strong&gt;workspaces&lt;/strong&gt; and &lt;strong&gt;folders&lt;/strong&gt; so you can now create the right space for all your team’s docs.&lt;/p&gt;

&lt;p&gt;You can think of folders like shared doc lists. So when someone joins the team, rather than add them to every doc one by one, just add them to the team folder and they’ll get access to all the docs automatically. You’ll also see a “My Docs” folder, which is your private sandbox or working area. When you’re ready to deploy a doc to your team, simply drop it into the team folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dHGSsXGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cl.ly/9560f6ba9731/4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dHGSsXGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cl.ly/9560f6ba9731/4.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building blocks for serious teams. (Cross-doc is here.)
&lt;/h2&gt;

&lt;p&gt;Now for your most requested features.&lt;/p&gt;

&lt;p&gt;Coda 2.0 also includes &lt;strong&gt;Locking&lt;/strong&gt; at the doc and section level, so teams can ensure important information stays put. On top of that, we’re adding &lt;strong&gt;Permissions&lt;/strong&gt; (coming soon) so makers can ensure people are only interacting with the information they should be editing. So you’ll never have to worry about accidentally deleting your company OKR table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DVJCKkwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cl.ly/8ac8f1a1a54e/5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DVJCKkwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cl.ly/8ac8f1a1a54e/5.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And by popular demand, we have &lt;strong&gt;Cross-doc&lt;/strong&gt;. We built Packs to integrate Coda with the other apps your team uses. And the number one Packs request wasn’t for another service, it was for another Coda doc! Cross-doc lets you pull data from one doc into another, so you can retain that ever-elusive single source of truth.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qxNCCFhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cl.ly/618f2f6128bb/6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qxNCCFhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cl.ly/618f2f6128bb/6.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cross-doc is no simple thing, and consider this a first iteration. We expect this building block in particular will likely reshape how you organize information in Coda. Instead of one megadoc with views for every team, you could now have one Coda doc for the master data set, feeding into separate team docs.&lt;/p&gt;

&lt;p&gt;And speaking of things cross-wise… we also have good news for your teammates who don’t use Chrome: Coda 2.0 includes cross-browser support. We now work on Chromium, Safari, with Firefox in beta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing for teams of all sizes.
&lt;/h2&gt;

&lt;p&gt;First of all, you’ll always be able to make docs as powerful as apps for freeーwhether that’s a to-do list, a meeting doc, or a wiki. As your docs evolve into bona-fide team tools, you’ll want to level up to a Pro, Team, or Enterprise plan.&lt;/p&gt;

&lt;p&gt;We’ve taken an unconventional approach to pricing, which we expect you’ll find fairer and cheaper than traditional models. Most of our competitors charge for everyone using a doc, even those who only touch it lightly. We only charge you for the people who make the docs. We call it Maker Billing. Learn more &lt;a href="https://coda.io/pricing"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With Coda 2.0, we’re as convinced as ever that the maker generation is going to shape how work is done, and redefine what enterprise software looks like. Regardless of job titles — product managers, teachers, and event planners — there will always be a person who steps up to make the tool for their team. But to paraphrase John Donne, no maker is an island. With 2.0, our goal is to convert more contributors into makers, and empower the whole team to join in the making.&lt;/p&gt;

</description>
      <category>news</category>
      <category>startup</category>
    </item>
    <item>
      <title>Interview about being a remote worker on Remote Tools</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Mon, 07 Oct 2019 16:11:07 +0000</pubDate>
      <link>https://dev.to/coda/interview-about-being-a-remote-worker-on-remote-tools-3pm</link>
      <guid>https://dev.to/coda/interview-about-being-a-remote-worker-on-remote-tools-3pm</guid>
      <description>&lt;h2&gt;
  
  
  1. Hey, can you please introduce yourself?
&lt;/h2&gt;

&lt;p&gt;My name is Al, and I’m a solutions architect at &lt;a href="https://www.coda.io/"&gt;Coda&lt;/a&gt;. Coda is an all-in-one doc that gives you all the building blocks you need to run your team’s projects. A little bit about my history: I was born and raised in Michigan, went to NYC to study finance, and started my career at Google in the Bay area. &lt;/p&gt;

&lt;p&gt;During my time at Google I fell in love with data. I know that sounds a bit extreme, but I honestly wouldn’t be here today if it wasn’t for Excel spreadsheets, SQL, and the Internet. I’ve always had a fascination with computers and tech, and the last few years have experimented with multiple SaaS and cloud platforms. Before joining the Coda team, I was a freelance Excel consultant, and got really involved with the Excel community in NYC during my years as a freelancer. This photo is from the Modeloff Financial Modeling competition where Excel gurus from around the world “compete” to be the world’s best financial modeler. I’m proud to be a part of this community and encourage more Excel enthusiasts to participate!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nzrieYwJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3a-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nzrieYwJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3a-1.jpg" alt="Modeloff financial modeling competition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What motivated you to choose remote working?
&lt;/h2&gt;

&lt;p&gt;It was out of necessity, really. When I left Google to pursue my own startup and work as a freelancer, I bounced around my apartment, co-working spaces, coffee shops, and even the public library. I chased good Wi-Fi anywhere I could find it in NYC. It was strange at first since I was basically thrown into the remote world and didn’t have a playbook on how to do it. Like many things in life, I learned to adapt to my new world by buying the right equipment, packing my backpack properly if I planned on being out most of the day, and got really good at e-mail and writing notes.&lt;/p&gt;

&lt;p&gt;Over time, I realized two things about remote work that motivate me to continue a lifestyle of remote work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Productivity&lt;/strong&gt; – Without unnecessary meetings and face-to-face time, I am extremely productive and am able to block off large parts of my day for &lt;a href="https://verilymag.com/2018/09/why-deep-work-matters-to-your-productivity-and-how-to-make-it-part-of-your-routine"&gt;deep work&lt;/a&gt;.&lt;br&gt;
&lt;strong&gt;2. Flexibility&lt;/strong&gt; – By not having to go into an office every day, I am able to work from anywhere which means I can travel if I want to, run errands in the middle of the day, and do things that I otherwise wouldn’t be able to do if I was in a 9-to-5 job.&lt;/p&gt;

&lt;p&gt;With my current role at Coda, I am still working remotely in NYC but there is a little more structure to my day (which I like). I definitely appreciate the nomadic lifestyle, but it’s not something I could do for a month or year. Having a weekly cadence to my meetings and projects does give me a sense of stability and also keeps me “plugged in” with the rest of my team on the west coast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WNwKlaes--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3b-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WNwKlaes--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3b-1.png" alt="Coda office desk setup"&gt;&lt;/a&gt;&lt;/p&gt;
My current workplace setup



&lt;h2&gt;
  
  
  3. What were your initial months like? Did it live up to your expectations?
&lt;/h2&gt;

&lt;p&gt;I can speak to my first few months at Coda, since I started working remotely right after I joined the company. I didn’t have a physical office yet, so my first few months were spent at home. It was definitely hard to work from home because Wi-Fi in NYC is notoriously unreliable, and my apartment building is no different. My Zoom calls would be very choppy and other things would just be slow. Makes you really appreciate good Wi-Fi!&lt;/p&gt;

&lt;p&gt;Nonetheless, my experience was really positive because I was able to adapt my schedule to that of my colleagues on the west coast. Since I knew they were generally still asleep from 9-12PM ET, I did a lot of errands and went to the gym in the mornings since there is less going on then.&lt;/p&gt;

&lt;p&gt;Pushing all my personal responsibilities to the morning had a different impact on my life. Tim Ferriss has talked about morning rituals to &lt;a href="https://www.inc.com/chris-winfield/5-morning-rituals-that-help-you-win-the-day-.html"&gt;win your mornings&lt;/a&gt;, and it can be something as simple as making your bed. For me, I’ve already gone to the gym, went to the doctor, fixed a leaky toilet, and wrote a blog post before my team has even woken up. All these activities allow me to “win my mornings” and makes me feel accomplished before my day has officially started. &lt;/p&gt;

&lt;p&gt;This is why I wouldn’t succeed as a true digital nomad. Having some structure and routine to my day means I can accomplish small goals and then work on the big projects with the broader Coda team. As a digital nomad, you are most likely jumping from project to project the entire day, and I feel that it may be more difficult to “win” the morning in these cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. How did you find remote working roles?
&lt;/h2&gt;

&lt;p&gt;The way I found my current role was through my friends and professional network. There are countless websites with job postings for remote workers, but I think if the company really values your skillset and more importantly, wants to stay competitive in the current business environment, they have to embrace remote workers.&lt;/p&gt;

&lt;p&gt;Had it not been for some strong referrals from previous colleagues, I don’t think my current company would’ve been open to me working remotely. Having said that, I spent a lot of time the first 3-6 months traveling to the west coast to build relationships with the team since I didn’t want to be that one person who everyone just knows through a small Zoom window. Some people think that remote work means you can just hide away and never interact with colleagues who care about you more than just the work you produce. I think one of the most important aspects of remote work is putting in the extra effort to get to know your team whether they are distributed or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. What have been the best, good and worst aspects of remote working for you?
&lt;/h2&gt;

&lt;p&gt;The best aspects of remote work are &lt;strong&gt;flexibility&lt;/strong&gt; and &lt;strong&gt;productivity&lt;/strong&gt; as I mentioned earlier. I am currently in a WeWork co-working space, so another positive aspect is that I get to interact with others who are in a similar position as me. Many people here are also remote workers and we don’t get that intra-office feeling with people you share the same goals with. Instead, we can talk to each other about our experiences working remotely and it makes me feel like I have a trusted colleague right here in my office, even though they don’t work at the same company as me.&lt;/p&gt;

&lt;p&gt;The worst aspect for many, I presume, is loneliness. I get this question asked all the time by my friends but also my colleagues as well. I don’t feel lonely since I have been proactive about meeting others in my co-working space, attending meetups, and joining online communities that have similar professional interests as me. &lt;/p&gt;

&lt;p&gt;Personally, the worst aspect is not being able to have a casual coffee with my co-workers where I can get to know them on a personal level. While Zoom and Slack help with bridging the gap, nothing beats the 1:1 interaction you have when you can look into someone’s eyes and notice non-verbal cues. This is why I value my trips to the west coast so much to see my team!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zlZXdP0i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3c-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zlZXdP0i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3c-1.png" alt="Coda meetup at wework"&gt;&lt;/a&gt;&lt;/p&gt;
Picture of a meetup at my co-working space where I can interact with humans, yay!



&lt;h2&gt;
  
  
  6. What tools do you swear by while working remotely?
&lt;/h2&gt;

&lt;p&gt;I am biased here, but &lt;a href="https://www.coda.io/"&gt;Coda&lt;/a&gt; is my main tool for getting work done. The way my Coda docs have evolved and grown over time is a direct result of my team’s projects, culture, and cadence for getting work done. More importantly, everything we do internally is well documented (and I contribute to this documentation whenever I can) so that I can work asynchronously. Tools that allow you to work asynchronously are a big discovery for me as a remote worker, and I’m glad that Coda is part of this family. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ub1FTWhJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3d-1-1024x497.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ub1FTWhJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/3d-1-1024x497.png" alt="Chrome tabs"&gt;&lt;/a&gt;&lt;/p&gt;
Do you have a sea of Google Docs and Sheets tabs like this? If yes, you need to use Coda 🙂



&lt;p&gt;Coda has replaced all my Google Docs, Google Sheets, and some Google Slide decks so those are no longer tabs that take up space in my Chrome. As a remote worker, most of your time is probably spent in Chrome or Firefox where you’re building, writing, and creating in various online tools (unless you are working with specialized software like video editing software). Other digital tools are Slack and Zoom for communication and meetings with my team. One of the reasons I don’t feel lonely as a remote worker is because I have numerous Zoom meetings with my team out west so I have a lot of chances to catch up and engage some banter with my teammates. &lt;/p&gt;

&lt;p&gt;A physical tool I cannot live without is my &lt;a href="https://www.amazon.com/Mpow-Microphone-Cancelling-Lightweight-Headphones/dp/B06XWG12QS"&gt;headset&lt;/a&gt; which I bought for $20 on Amazon. Having a wired headset with a stick mic ensures good audio quality for my Zoom meetings and calls. Everyone hates being on calls where one person forgets to mute their mic, or there is a ton of static on the line. Don’t be that person when you work remotely! Invest in a good headset with a mic.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Your most exciting/ hilarious experience since you started working remotely.
&lt;/h2&gt;

&lt;p&gt;This is more of a logistical issue that led to a hilarious experience, but when I first started working remotely from my apartment the first few months, the air conditioner in my living room broke. It was the middle of a hot NYC summer and the living room is where I get all my work done and do all my Zoom calls. My bedroom has an AC unit, but it was too difficult to get work done there so I just stayed out in the humid living room.&lt;/p&gt;

&lt;p&gt;Inevitably, I would start working without a shirt on and would be constantly wiping sweat off my body. I dreaded Zoom calls while my air conditioner was getting fixed because I had to put on a shirt for the call, and my teammates could tell that I looked uncomfortable over video. I made it pretty clear that if it wasn’t for the Zoom call, I wouldn’t be wearing a shirt!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sMFklKm6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/image2-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sMFklKm6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://content.remote.tools/wp-content/uploads/2019/10/image2-1.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. What is your golden advice to a new remote worker?
&lt;/h2&gt;

&lt;p&gt;Main advice is to be a good communicator across all channels. This means e-mail, Slack, Zoom, online forums, etc. A lot of people say they have good “communication skills,” but it’s a whole other ballgame when it comes to remote work. If you are freelancing, some of your clients may have strict guidelines on project updates, check-ins, and coming on-site if necessary. Other clients may not have experience with hiring remote workers, so you have to establish the expectations and rules on how often you will communicate with your clients.&lt;/p&gt;

&lt;p&gt;When in doubt, over communicate. Log every decision, thought, idea, and mistake you make so that your colleague or client know exactly what went through your head as you complete your work. Then send regular emails and Slack messages with those updates so that your counterpart never has an excuse for missing your updates. &lt;/p&gt;

&lt;h2&gt;
  
  
  9. How do you see your career shaping up and your goals?
&lt;/h2&gt;

&lt;p&gt;I don’t have a 1-year or 5-year plan, since I think career paths are a bit too rigid especially for remote workers. Who starts their career knowing that they want to be a remote worker by year 4? It usually is a result of your personal circumstances and situation, rather than being driven by career aspirations. Having said that, my only goals as a remote worker is to continue building relationships with my teammates and helping our users succeed with our platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. How do you expect remote working to evolve in the future?
&lt;/h2&gt;

&lt;p&gt;I believe remote work will be more commonplace in the future and more co-working spaces will pop up to support these digital nomads and distributed teams. In the most extreme case (and this may not be that extreme in say 5 years), companies will have 100% distributed teams and we’ll all be connected through virtual worlds. The best example of this is this &lt;a href="https://www.businessinsider.com/exp-realty-virtual-office-campus-remote-2018-7"&gt;virtual real estate company&lt;/a&gt; that has 13,000 agents and staff but no physical office. They all stay “connected” through browsing around a virtual world like the Metaverse from Snow Crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Where can we follow you online?
&lt;/h2&gt;

&lt;p&gt;-Twitter: &lt;a href="https://twitter.com/bigal123"&gt;https://twitter.com/bigal123&lt;/a&gt;&lt;br&gt;
-Linkedin: &lt;a href="https://linkedin.com/in/thealchen"&gt;https://linkedin.com/in/thealchen&lt;/a&gt;&lt;br&gt;
-YouTube: &lt;a href="https://www.youtube.com/channel/UC8DXcQiNj9RI2eeNycIETdA"&gt;https://www.youtube.com/channel/UC8DXcQiNj9RI2eeNycIETdA&lt;/a&gt;&lt;br&gt;
-Blog: &lt;a href="https://medium.com/@alchen1"&gt;https://medium.com/@alchen1&lt;/a&gt; and &lt;a href="https://blog.coda.io/"&gt;https://blog.coda.io/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
      <category>remotework</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to deploy Craft CMS with Postgres on Heroku</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Tue, 01 Oct 2019 22:17:16 +0000</pubDate>
      <link>https://dev.to/coda/how-to-deploy-craft-cms-with-postgres-on-heroku-1c2h</link>
      <guid>https://dev.to/coda/how-to-deploy-craft-cms-with-postgres-on-heroku-1c2h</guid>
      <description>&lt;h2&gt;
  
  
  Moving your company blog from Medium to a subfolder
&lt;/h2&gt;

&lt;p&gt;Why did I start looking into a CMS in the first place? If you are in the SEO space, chances are you've explored this issue before. There are countless &lt;a href="https://medium.com/@pineappleaday/blog-as-domain-vs-subdirectory-which-is-better-for-seo-8582973a68c4" rel="noopener noreferrer"&gt;articles&lt;/a&gt; on the implications of having your company's blog on Medium versus a subfolder or subdomain under your main domain. Coda's &lt;a href="https://www.blog.coda.io" rel="noopener noreferrer"&gt;blog&lt;/a&gt; is on Medium and our subdomain &lt;code&gt;blog.coda.io&lt;/code&gt; points to it. This project started as a way for me to experiment with new CMSs to move Coda's blog to a new CMS and ultimately to a subfolder under Coda's main domain. &lt;/p&gt;

&lt;h2&gt;
  
  
  Other use cases for a CMS
&lt;/h2&gt;

&lt;p&gt;As my team and I thought about which CMS to use, we started thinking about other requirements for the CMS. Can the CMS be used for other parts of our website? How secure is it? How does it handle image compression? Long story short, we are still experimenting and exploring different CMSs but I wanted to document my explorations with &lt;a href="https://craftcms.com" rel="noopener noreferrer"&gt;Craft&lt;/a&gt;. Heard about it from some Slack community and just started poking around and came across various &lt;a href="https://www.youtube.com/user/mijingollc" rel="noopener noreferrer"&gt;videos&lt;/a&gt;, &lt;a href="https://craftcms.stackexchange.com/" rel="noopener noreferrer"&gt;Stack Exchange&lt;/a&gt; community, and even a &lt;a href="https://devmode.fm/" rel="noopener noreferrer"&gt;podcast&lt;/a&gt; hosted by &lt;a class="mentioned-user" href="https://dev.to/gaijinity"&gt;@gaijinity&lt;/a&gt; (among others). So far, so good. Lot of places I can seek help if I'm stuck. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying on Heroku was not as easy as I thought
&lt;/h2&gt;

&lt;p&gt;Speaking of places to get help, the first thing I did was try to find a good tutorial on how to deploy Craft to Heroku. I wouldn't be writing this tutorial had I found one that worked exactly as I needed it to :). The first guide that got me 75% of the way there was &lt;a href="https://torbensko.com/posts/2019/creating-a-site-using-craftcms-heroku-and-cloudcannon/" rel="noopener noreferrer"&gt;this one&lt;/a&gt; from Torben Sko. In that guide, he or she goes into some of the Postgres stuff I'm not super familiar with. Some other resources about Craft in general:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nystudio107.com/blog/setting-up-a-craft-cms-3-project" rel="noopener noreferrer"&gt;Setting up a new Craft 3 project&lt;/a&gt;&lt;/strong&gt; - Probably best overall tutorial (not about Heroku) for setting up Craft by &lt;a class="mentioned-user" href="https://dev.to/gaijinity"&gt;@gaijinity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/edenspiekermann/craft3-heroku-starterkit" rel="noopener noreferrer"&gt;Craft 3 Starter kit&lt;/a&gt;&lt;/strong&gt; by &lt;a href="https://github.com/mguth" rel="noopener noreferrer"&gt;Moritz Guth&lt;/a&gt; provides a good alternative method for deploying to Heroku (using the app.json file).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://chrishallahan.com/blog/using-craft-cms-to-build-modern-website" rel="noopener noreferrer"&gt;Chris Hallahan&lt;/a&gt;&lt;/strong&gt; - Good guide on customizing Craft&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://onesignal.com/blog/craft-cms/" rel="noopener noreferrer"&gt;OneSignal&lt;/a&gt;&lt;/strong&gt; - Another guide on overall benefits of Craft (see their &lt;a href="https://onesignal.com/blog/" rel="noopener noreferrer"&gt;blog&lt;/a&gt; as an example of a blog built on Craft)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hub.docker.com/r/wyveo/craftcms-docker/" rel="noopener noreferrer"&gt;Craft Docker base&lt;/a&gt;&lt;/strong&gt; - Exploring deploying on Docker next&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://mattgrayisok.com/developing-with-craft-cms-3-in-docker" rel="noopener noreferrer"&gt;Matt Grayisok&lt;/a&gt;&lt;/strong&gt; - Another tutorial for Craft and Docker&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ok so now onto the steps that I've gathered from the above resources and just playing around with stuff. If something doesn't work or is incorrect, let me know in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a project directory and run the Craft installtion
&lt;/h2&gt;

&lt;p&gt;This is for Craft 3. All instructions are on the &lt;a href="https://docs.craftcms.com/v3/installation.html" rel="noopener noreferrer"&gt;Craft website&lt;/a&gt;. Create a directory in terminal, go into that directory, and run &lt;code&gt;composer create-project craftcms/craft .&lt;/code&gt; (make sure you have &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt; installed). You'll get a screen that looks like this if done correctly:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2Ff2db46f0ecd7%2FImage%25202019-09-30%2520at%25209.18.52%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2Ff2db46f0ecd7%2FImage%25202019-09-30%2520at%25209.18.52%2520PM.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Setup Postgres locally
&lt;/h2&gt;

&lt;p&gt;A few commands here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;brew install postgres&lt;/code&gt; to install Postgres&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;brew services start postgresql&lt;/code&gt; to start Postgres&lt;/li&gt;
&lt;li&gt;Create a super user by following the prompts after you run &lt;code&gt;createuser --interactive --pwprompt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a database with &lt;code&gt;createdb -O [USERNAME] -Eutf8 [DATABASE]&lt;/code&gt;. Replace [USERNAME] with what you created in the last step. Replace [DATABASE] with whatever you want to call your database.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Step 3: Run Craft setup
&lt;/h2&gt;

&lt;p&gt;This is simply running &lt;code&gt;craft setup&lt;/code&gt; from your project directory. There was some reason to enter a tilda in front of the setup command but can't remember what it was, so for me it looked like this: &lt;code&gt;~/coda/craft-test/craft setup&lt;/code&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Settings asked during the setup phase
&lt;/h2&gt;

&lt;p&gt;You'll get asked a series of prompts during the setup phase. Most of the settings you can just hit ENTER for the default but there are a few to be aware of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When asked for database driver, enter &lt;code&gt;pgsql&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Server name should be the default &lt;code&gt;localhost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Port should be 5432&lt;/li&gt;
&lt;li&gt;Enter the Postgres username, password, and database name from step 2 when prompted&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hit "yes" when prompted to install Craft and you'll be asked to create a Craft username and password as well for the Craft admin interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Editing the db.php file
&lt;/h2&gt;

&lt;p&gt;This is code taken from &lt;a href="https://torbensko.com/posts/2019/creating-a-site-using-craftcms-heroku-and-cloudcannon/" rel="noopener noreferrer"&gt;Torben Sko&lt;/a&gt;, so just replace whatever is in your /config/db.php file with the following code:&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="nb"&gt;preg_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'|postgres://([a-z0-9]*):([a-z0-9]*)@([^:]*):([0-9]*)/(.*)|i'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DATABASE_URL'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"pgsql"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'server'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'database'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'schema'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_SCHEMA'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="s1"&gt;'tablePrefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_TABLE_PREFIX'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="s1"&gt;'port'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$port&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This code takes the &lt;code&gt;DATABASE_URL&lt;/code&gt; environment variable from your Heroku setup (which is one long URL) and parses it for the properties that Craft needs in order to make a connection with your Postgres database. More on this later.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Editing your local &lt;code&gt;.env&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;In order for Craft to run &lt;em&gt;locally&lt;/em&gt;, you need to add the following code to your local &lt;code&gt;.env&lt;/code&gt; file (which should not be committed to git):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DATABASE_URL="postgres://[POSTGRES USERNAME]:@localhost:5432/[POSTGRES DB NAME]"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Replace [POSTGRES USERNAME] and [POSTGRES DATABASE] with your Postgres setup from step 2. The &lt;code&gt;.env&lt;/code&gt; file in your local project directory has a few variables that may be important for your Heroku setup.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 7: Create a Heroku app
&lt;/h2&gt;

&lt;p&gt;I'll assume you have the &lt;a href="https://devcenter.heroku.com/articles/heroku-cli" rel="noopener noreferrer"&gt;Heroku CLI&lt;/a&gt; so run &lt;code&gt;heroku create&lt;/code&gt; to create a Heroku app and provision the &lt;a href="https://elements.heroku.com/addons/heroku-postgresql" rel="noopener noreferrer"&gt;Postgres Heroku add-on&lt;/a&gt; under "Resources":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2Fbbc5b0a0661f%2FImage%25202019-09-30%2520at%252010.58.20%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2Fbbc5b0a0661f%2FImage%25202019-09-30%2520at%252010.58.20%2520PM.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 8: Edit the Config Vars in Heroku
&lt;/h2&gt;

&lt;p&gt;This is one of those "gotchas" that I didn't really find in any tutorial. Under "Settings", you'll see a "Reveal Config Vars" button and this is where you'll define environment variables in Heroku (similar to the variables in your local &lt;code&gt;.env&lt;/code&gt; file). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2F557e7a6f93c4%2FImage%25202019-09-30%2520at%252010.59.55%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2F557e7a6f93c4%2FImage%25202019-09-30%2520at%252010.59.55%2520PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Config vars, you'll already see an entry for the &lt;code&gt;DATABASE_URL&lt;/code&gt; from when you provisioned the Postgres db in step 7. However, you'll need to add a few variables from our &lt;em&gt;local&lt;/em&gt; .env file to the &lt;em&gt;Heroku&lt;/em&gt; config vars:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ENVIRONMENT&lt;/code&gt; should be "dev" (you will most likely change this when your website is ready for production)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SECURITY_KEY&lt;/code&gt; is the random string of characters in the &lt;code&gt;SECURITY_KEY&lt;/code&gt; variable in your .env file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DB_SCHEMA&lt;/code&gt; should be "public"&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Step 9: Push your local Postgres db to Heroku
&lt;/h2&gt;

&lt;p&gt;Also from the Torben Sko article, you should run the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;heroku pg:reset DATABASE_URL --app [HEROKU APP NAME]&lt;/code&gt; to reset the Postgres db on Heroku (should be empty anyway)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heroku pg:push [LOCAL POSTGRES DB NAME] DATABASE_URL --app [HEROKU APP NAME]&lt;/code&gt; to push your local Postgres db to the Heroku&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Step 9: Create a Procfile
&lt;/h2&gt;

&lt;p&gt;This is something needed for Heroku, so you just create a file at your root directory called &lt;code&gt;Procfile&lt;/code&gt; with no extension and add the following line to this file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web: vendor/bin/heroku-php-apache2 web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In other tutorials, I've seen an alternative nginx server you can add to the &lt;code&gt;Procfile&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;web: vendor/bin/heroku-php-nginx -C nginx_app.conf web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Up to you on which one to use. The latter one requires you to add another file to your root folder (&lt;code&gt;nginx_app.conf&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 10: Add the PHP ImageMagick extension to Composer
&lt;/h2&gt;

&lt;p&gt;If you don't have this extension in your &lt;code&gt;composer.json&lt;/code&gt; file, you'll get this error when trying to navigate to the admin page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2Fd2df9f44b405%2FImage%25202019-10-01%2520at%25205.29.48%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2Fd2df9f44b405%2FImage%25202019-10-01%2520at%25205.29.48%2520PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;"ext-imagick": "*",&lt;/code&gt; under the require section in your &lt;code&gt;composer.json&lt;/code&gt; file like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2F99c0a9569d65%2FImage%25202019-10-01%2520at%25205.32.10%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2F99c0a9569d65%2FImage%25202019-10-01%2520at%25205.32.10%2520PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, you may run into an error when running &lt;code&gt;composer update&lt;/code&gt; as stated &lt;a href="https://github.com/Homebrew/homebrew-core/issues/26408" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I can't find the resources to solve this issue right now, but it basically involved removing a symlink to the &lt;code&gt;imagick.so&lt;/code&gt; package in your /usr/local/Cellar directory and then installing the &lt;code&gt;imagick&lt;/code&gt; package again with &lt;a href="https://pecl.php.net" rel="noopener noreferrer"&gt;&lt;code&gt;pecl&lt;/code&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Then run &lt;code&gt;composer update&lt;/code&gt; in terminal. This will update your &lt;code&gt;composer.lock&lt;/code&gt; file as well. It's really important to &lt;code&gt;git add&lt;/code&gt; and &lt;code&gt;commit&lt;/code&gt; changes at this point so that your &lt;code&gt;composer.lock&lt;/code&gt; file is up to date with &lt;code&gt;composer.json&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 11: Run Craft locally with Valet
&lt;/h2&gt;

&lt;p&gt;Instead of setting up MAMP or LAMP, this solution for running websites locally from &lt;a href="https://www.youtube.com/watch?v=eZVIDQjp8ro" rel="noopener noreferrer"&gt;Ryan Irelan&lt;/a&gt; is such an easier way to go. Having futzed around before with &lt;code&gt;.htaccess&lt;/code&gt; files and various permissions, &lt;a href="https://laravel.com/docs/5.8/valet" rel="noopener noreferrer"&gt;Laravel Valet&lt;/a&gt; is by far the &lt;em&gt;easiest&lt;/em&gt; solution I've used so far for getting a website up and running locally. You just run &lt;code&gt;valet link&lt;/code&gt; while in your project directory and then &lt;code&gt;valet secure&lt;/code&gt; to add SSL to your local website. You'll then have internal links like these below you can use to run Craft (or any project) locally:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2F707bfe796325%2FImage%25202019-10-01%2520at%25205.41.54%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcl.ly%2F707bfe796325%2FImage%25202019-10-01%2520at%25205.41.54%2520PM.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 12: Finishing up
&lt;/h2&gt;

&lt;p&gt;Commit all your changes and push to Heroku. If everything was setup correctly, you'll see your local &lt;code&gt;.dev&lt;/code&gt; page on your Heroku remote!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpninb5in0ypralwnkj3k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpninb5in0ypralwnkj3k.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's my public repo in case you're interested in seeing my setup:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/al-codaio" rel="noopener noreferrer"&gt;
        al-codaio
      &lt;/a&gt; / &lt;a href="https://github.com/al-codaio/coda-blog" rel="noopener noreferrer"&gt;
        coda-blog
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
    </item>
    <item>
      <title>How I Stumbled Into Remote Work And Never Looked Back</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Tue, 10 Sep 2019 16:10:48 +0000</pubDate>
      <link>https://dev.to/coda/how-i-stumbled-into-remote-work-and-never-looked-back-51c4</link>
      <guid>https://dev.to/coda/how-i-stumbled-into-remote-work-and-never-looked-back-51c4</guid>
      <description>&lt;p&gt;I never thought I'd be a remote worker. Growing up in the 90s, I saw my dad go to work with his briefcase and get home every day around the same time. There was no talk of "work" once he returned home. I thought clocking in and clocking out at a place you called "work" was the norm and that was going to be my life once I graduated college. I never saw this type of employment as "good" or "bad," it was just the way things were back then.&lt;/p&gt;

&lt;p&gt;I wanted to reflect on how I became a remote worker, and how I can't see doing "work" any other way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating spreadsheets on a hallway floor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fRn23qP0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.akitasmexico.com/wp-content/uploads/2017/05/84f18a065b42f13b729f5706bfa35066.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fRn23qP0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.akitasmexico.com/wp-content/uploads/2017/05/84f18a065b42f13b729f5706bfa35066.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Source: Akitas Mexico



&lt;p&gt;I started my career as a financial analyst, and remember visiting New York for a few days just because I wanted to see some friends. My team was based in San Francisco, so I still had to work west coast hours. I stayed at a friend's place and still remember vividly sitting in their cramped apartment hallway at 11PM updating a spreadsheet that needed to be uploaded to the Oracle server.&lt;/p&gt;

&lt;p&gt;Back then (~2008), laptops did not necessarily have a Wi-Fi component built into the hardware, so I had this USB stick that could pick up Wi-Fi or tap into the data plan my team had. Of course, updates were super slow and I just sat there waiting for the changes in my spreadsheet to finish uploading to the server. In that moment, I realized my "work" was simply updating a database by a due date (month-end close). It didn't matter where or how I did it--as long as it got done that's all that matters to my team and company.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bikes and bean bags
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--abPLlOKy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/2/25/Bean_Bags_at_GDD.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--abPLlOKy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/2/25/Bean_Bags_at_GDD.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Source: Wikimedia Commons



&lt;p&gt;The company I was lucky enough to work at was Google. Google's interior design is unlike most companies. Everything from the snack kitchens to commons spaces are playfully designed making the workplace a really fun place to, well, work. Common spaces would be filled with chairs, couches, and bean bags.&lt;/p&gt;

&lt;p&gt;My first year at Google, I saw people just lounging around on these bean bags and working on their computers. At first, I thought this was insane. Why weren't these employees at their desks? Won't their bosses be mad because they don't have "face time" with their subordinates? This was just the culture, and employees can work wherever they feel comfortable as long as the work gets done.&lt;/p&gt;

&lt;p&gt;The headquarters in Mountain View is a sprawling campus of buildings. If you had a meeting on the other side of campus, you would have to budget 10-15 minutes to take a shuttle to the other side of campus, or jump on a bike and put your laptop in the little basket on the front of the bike. I would kind of play it by ear on whether or not I should go to meetings in person to save time on the "commute," but I could easily dial into a meeting with Google Hangouts from some other conference room or from my laptop (while sitting on a bean bag, of course). I got all the information I needed to do my work, and saved 20-30 minutes of commuting to another part of campus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scratching the entrepreneurial itch
&lt;/h2&gt;

&lt;p&gt;After I started pursuing my own startup and doing freelance work, I found myself bouncing between coffee shops, the public library, and my apartment. I realized I could also travel and get work done as long as the hostel or apartment had Internet. The best part about this period of my career was I discovered 3 skills that have helped me to this day:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to learn digitally&lt;/li&gt;
&lt;li&gt;How to communicate digitally&lt;/li&gt;
&lt;li&gt;How to write proper documentation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I started taking online classes to pick up quick skills on web development. I learned some of the nuances about posting in online forums and writing blog posts. As I scaled my company, I focused on writing good documentation outlining our processes and systems. Whenever there was a problem to be solved, I instantly think about solving the solution digitally. I think this was one of the best parts about going off on my own: learning to solve problems without a &lt;em&gt;company&lt;/em&gt; to support you when you mess things up. I had to be scrappy and cost-efficient, and the best way was to use as many online resources as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing skills for remote work
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5JxMmQlC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static1.squarespace.com/static/5772d5b09de4bb81b44f2253/5772d80715d5db1a2b8e9901/5ab3aa22352f5348400870bc/1521730544309/nathan-riley-514162-unsplash.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5JxMmQlC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static1.squarespace.com/static/5772d5b09de4bb81b44f2253/5772d80715d5db1a2b8e9901/5ab3aa22352f5348400870bc/1521730544309/nathan-riley-514162-unsplash.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Source: yonder.io



&lt;p&gt;Despite all the trends pointing to more companies moving to remote work, there will always be people that need to go to a physical office every day and have face time with their colleagues and management. On the flip side, your personal circumstances may force you to be a remote worker, and you'll have to develop these skills as best you can since you don't have a choice. Here are my tips for gaining the skills to be a solid remote worker:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Observe employees at other companies
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KK2EiSsT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.nreionline.com/sites/nreionline.com/files/styles/article_featured_standard/public/wework-timessquare.jpg%3Fitok%3D6kEavCSF" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KK2EiSsT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.nreionline.com/sites/nreionline.com/files/styles/article_featured_standard/public/wework-timessquare.jpg%3Fitok%3D6kEavCSF" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Source: nreionline



&lt;p&gt;Just like my initial experience seeing people working on bean bags at Google, seeing how other companies work with remote workers can broaden your horizons on what arrangements are possible. An easy way to do this is ask for a tour of any WeWork and ask a few people how they get their work done. What tools do they use? How do they attend meetings?&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Join online communities related to your industry
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gxrRKJEG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gannett-cdn.com/-mm-/cc3b936ffa25ef0e3d78b46b663d8b777dbbfc3e/c%3D0-0-1985-1122/local/-/media/2017/08/29/USATODAY/USATODAY/636396027514371231-reddit-front.jpg%3Fwidth%3D3200%26height%3D1680%26fit%3Dcrop" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gxrRKJEG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.gannett-cdn.com/-mm-/cc3b936ffa25ef0e3d78b46b663d8b777dbbfc3e/c%3D0-0-1985-1122/local/-/media/2017/08/29/USATODAY/USATODAY/636396027514371231-reddit-front.jpg%3Fwidth%3D3200%26height%3D1680%26fit%3Dcrop" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Source: USA Today



&lt;p&gt;I used to think online communities and forums were simply places to find answers to a problem you are trying to solve (still a great resource for that!). How do you set up a Facebook Ads campaign? How do you set your Shopify store? These are all common questions you might ask and get answers to. But once you are remote, the individuals in these communities &lt;em&gt;become&lt;/em&gt; your co-workers, to a certain extent. In addition to finding answers to questions about some esoteric problem, online communities can expand how you think about your work and give you a chance to connect with another human (albeit digitally). The &lt;a href="https://www.linkedin.com/groups/13657237/"&gt;Digital Nomads on LinkedIn&lt;/a&gt; group is a great place to start if you want to get more tips on working remotely.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Write detailed and thorough documentation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YEZVVWG0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://sabezahr.com/wp-content/uploads/2017/07/button-documentation.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YEZVVWG0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://sabezahr.com/wp-content/uploads/2017/07/button-documentation.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Sabeza HR



&lt;p&gt;If you have colleagues, this is probably the #1 skill I would prioritize. How many times have you been asked something like this on Slack: "Hey Bob, what is the process for uploading pictures into our CMS?" You could easily respond over Slack, but that isn't scalable. Creating a document or wiki where you detail the process for saving the image, logging into the CMS, and inserting the image means every single colleague and future employee has one single source of truth to understand your process. This skill extends to documenting meetings, decisions made, customer interviews, and more. Think about all the online SaaS tools you use. Whenever you have a question about how something works, you might Google the question, and the best SaaS tools have great documentation that gives you step-by-step instructions on how to fix your problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating routines and consistency
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oZjpVUfD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.pinimg.com/originals/e8/66/e8/e866e8b5e342477357f7cbcfe956660a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oZjpVUfD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.pinimg.com/originals/e8/66/e8/e866e8b5e342477357f7cbcfe956660a.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
One observation I've seen at other companies (including &lt;a href="https://www.coda.io"&gt;my own&lt;/a&gt;) is people will go to work at a physical location, and then put on noise-canceling headphones to get their "work" done. I'm not going to get into the whole debate around open workspaces, but there's a lot of talk these days about getting into a &lt;a href="https://en.wikipedia.org/wiki/Flow_(psychology)"&gt;flow state&lt;/a&gt; or "the zone." This usually means being engulfed in your current task and not being interrupted while you work. By creating that environment where you can work uninterrupted for a long period of time, you gain more consistency with getting your work done effectively.&lt;/p&gt;

&lt;p&gt;I still enjoy the routine of going to my office (a co-working space), having a desk that I can call my own, and my go-to lunch spots around the office. On the spectrum of one end of needing to go into the office every day for face time, and the other end being a true nomad where your location changes every day/week, I would fall somewhere between the middle of the spectrum and the complete nomad extreme. I cannot fathom needing to go to an office every day for face time, nor can I see myself traveling every day where I'm not sure if the Internet is stable to get my work done and I don't know where I can get lunch. There is still a semblance of a daily routine where I've found I can get the maximum output while still enjoying the benefits of remote work.&lt;/p&gt;

</description>
      <category>remote</category>
      <category>career</category>
      <category>productivity</category>
      <category>remotework</category>
    </item>
    <item>
      <title>Hacker Ethic from Building the ITS system in the 1960s</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Wed, 03 Jul 2019 18:18:29 +0000</pubDate>
      <link>https://dev.to/coda/hacker-ethic-from-building-the-its-system-in-the-1960s-3de0</link>
      <guid>https://dev.to/coda/hacker-ethic-from-building-the-its-system-in-the-1960s-3de0</guid>
      <description>&lt;p&gt;I'm currently reading Steven Levy's &lt;em&gt;Hackers&lt;/em&gt; and came across this quote which I thought was worth sharing. I think it not only embodies the &lt;a href="https://en.wikipedia.org/wiki/Hacker_ethic"&gt;hacker ethic&lt;/a&gt;, as Levy describes, but also provides a glimpse into the future. One day, everyone will be their own designer, implementor, and user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--840xBrss--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/udaqiglivb5x9rmcu4z9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--840xBrss--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/udaqiglivb5x9rmcu4z9.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's full the quote from Don Eastlake:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The ITS system is not the result of a human wave or crash effort. The system has been incrementally developed almost continuously since its inception. It is indeed true that large systems are never "finished." ...In general, the ITS system can be said to have been designer implemented and user designed. The problem of unrealistic software design is greatly diminished when the designer is the implementor. The implementor's ease in programming and pride in the result is increased when he, in an essential sense, is the designer. Features are less likely to turn out to be of low utility if users are their designers and they are less likely to be difficult to use if their designers are their users.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How to sync data between Coda docs (and Google Sheets) using Google Apps Script</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Tue, 21 May 2019 15:42:25 +0000</pubDate>
      <link>https://dev.to/coda/how-to-sync-data-between-coda-docs-and-google-sheets-using-google-apps-script-2adc</link>
      <guid>https://dev.to/coda/how-to-sync-data-between-coda-docs-and-google-sheets-using-google-apps-script-2adc</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://coda.io/@atc/how-to-sync-data-between-coda-docs-and-google-sheets-using-googl"&gt;Coda profile&lt;/a&gt; (coda.io/@atc).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;May 2020 update&lt;/strong&gt;: Published two scripts to sync from Coda to Google Sheets or from Google Sheets to Coda. See &lt;a href="https://coda.io/@atc/how-to-sync-data-from-coda-to-google-sheets-and-vice-versa-with-google-apps-script-tutorial"&gt;this post&lt;/a&gt; for details.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Feb 2020 update&lt;/strong&gt;: If you are using the &lt;a href="https://developers.google.com/apps-script/guides/v8-runtime"&gt;V8 runtime&lt;/a&gt; in Google Apps Script, delete the word each from &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L40"&gt;line 40&lt;/a&gt; and &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L88"&gt;line 88&lt;/a&gt; of the script.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You have a master spreadsheet with some sensitive data, but want to share &lt;em&gt;some&lt;/em&gt; of that data with a client, employee, or vendor. You obviously can’t share the entire spreadsheet because then the other party can see your sensitive data. I’ve seen this scenario over and over again in various workflows, and there are some solutions that solve this problem…but they’re not perfect. So what do you do?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2txybZBB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A_NhXGy8JWUYQ7nLk" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2txybZBB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A_NhXGy8JWUYQ7nLk" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there is software that exists specifically for your industry, then you’re in luck. Chances are that specialized software has built in data sync features that allow you to see the data that is important to you, but then you can share a filtered view of that data with your client or patient. The other party most likely has to set up a login on the software you use, or download an app to see their data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Then there’s the rest of us.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We spend our lives in Excel spreadsheets and Google Sheets, and needs simple ways to share data &lt;em&gt;between&lt;/em&gt; the files. In this article, I’m going to discuss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to share data from one table in a Coda doc to another Coda doc using &lt;a href="https://developers.google.com/apps-script/"&gt;Google Apps Script&lt;/a&gt; (GAS)&lt;/li&gt;
&lt;li&gt;How to share data from one Google Sheet to another Google Sheet (also using GAS)&lt;/li&gt;
&lt;li&gt;A non-GAS way to share data from one Google Sheet to another Google Sheet using formulas&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;If you want to skip right to the solution, here is the&lt;/em&gt; &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5"&gt;&lt;em&gt;script for syncing Coda tables&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and the script for syncing Google Sheets lists. Or just watch the video below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PL_uSeKmYkc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  First off, what is Coda?
&lt;/h3&gt;

&lt;p&gt;Coda is a real-time collaborative doc (similar to a Google Doc) that includes the power of spreadsheets and databases in one tool. With Coda, you’re able to build applications (without code) that solve workflows related to &lt;a href="https://coda.io/templates/project-management"&gt;project management&lt;/a&gt; to organizing &lt;a href="https://coda.io/t/Game-of-Thrones-Death-Pool_thh_XTvB5YN"&gt;Game of Thrones death pools&lt;/a&gt;for your friends. See the video below if you’re more of a visual learner:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/M2tNj1CYp_A"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;At the heart of Coda are tables of data. Tables in Coda look and feel like a grid of cells in a spreadsheet, but they have names and act more like databases. Here is a table of team tasks with typical columns you would need for managing tasks for a project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H8GtDVCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AX5FhryK4pEzOkRONJXLubA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H8GtDVCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AX5FhryK4pEzOkRONJXLubA.png" alt=""&gt;&lt;/a&gt;Table of project tasks in Coda&lt;/p&gt;

&lt;h3&gt;
  
  
  Filtering data that’s relevant for you
&lt;/h3&gt;

&lt;p&gt;If you are the project manager, this list could get pretty long so what most project managers would do is &lt;a href="https://help.coda.io/getting-started/using-coda/creating-a-view"&gt;create a view&lt;/a&gt; of the tasks filtered to just tasks that have a Stage of “Not Started” or the “Industrial Design” team would create a view of the tasks just filtered to their team.&lt;/p&gt;

&lt;p&gt;Many users in the Coda community want to sync the data from a master task list above to a separate Coda doc. Why? To create an even cleaner view of the tasks that doesn’t include the other sections of the “source” doc. Some common workflows outside of project management I’ve seen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;digital agency&lt;/strong&gt; manages their clients’ data in a doc, but wants to selectively share data from their doc with their clients&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;teacher&lt;/strong&gt; tracks their students’ attendance and grade in one Coda doc, but only wants to share data specific to one student with that student’s parents&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;small business&lt;/strong&gt; manages their business data in a doc and places purchase orders with vendors, and only wants to share specific data from their doc with one vendor&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enter Google Apps Script
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pcthuOVY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/440/1%2Av_7LgWIFY9E_DEm6Wok_KQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pcthuOVY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/440/1%2Av_7LgWIFY9E_DEm6Wok_KQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can integrate all the various apps you use from Google (e.g. Gmail, Google Sheets, Google Docs) using Google Apps Script. Coda has a library you can use in Google Apps Script, which means you can integrate data from Coda with other Google apps (and vice versa).&lt;/p&gt;

&lt;p&gt;I find that using the &lt;a href="https://coda.io/developers/apis/v1beta1#section/Introduction"&gt;Coda API&lt;/a&gt; is easiest with GAS, but you can also use Python or a Unix shell. What I like about using GAS for syncing tables in Coda docs together is that you can easily set up a &lt;a href="https://developers.google.com/apps-script/guides/triggers/installable"&gt;time-driven trigger&lt;/a&gt; so that your script runs every minute, hour, day, etc. If you are using Google Sheets, however, you can use &lt;a href="https://developers.google.com/apps-script/guides/triggers/"&gt;simple triggers&lt;/a&gt; that fire your script when there is a change to one of your Google Sheets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up your Google Apps Script
&lt;/h3&gt;

&lt;p&gt;If you follow along with the &lt;a href="https://coda.io/t/Getting-Started-Guide-Coda-API_toujpmwflfy"&gt;Getting Started Guide: Coda API&lt;/a&gt;, you’ll pretty much get the one-way sync working so that data from your master Coda doc (which I’ll call the &lt;em&gt;source&lt;/em&gt; from now on) is one-way synced to another Coda doc you create (the &lt;em&gt;target&lt;/em&gt; doc). See the full script below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The main function you need to run is &lt;code&gt;oneWaySync()&lt;/code&gt; and the table from your source doc will get synced to a table you define in your target doc. After playing around with this script, I noticed there are a few things we can do to make the script more robust to solve more complicated workflows and data sync scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  #1 Sync multiple tables in the source to multiple tables in the target
&lt;/h3&gt;

&lt;p&gt;If you look at the way the script is structured, it assume two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have multiple tables in your source doc you want to sync&lt;/li&gt;
&lt;li&gt;There is only one table in your target doc that all the multiple tables sync to&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the part of the script where you define your source and target tables and the &lt;code&gt;syncSpecificTable()&lt;/code&gt; function syncs each of the source tables with your target table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;SOURCE_TABLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Source Table&lt;/span&gt;&lt;span class="dl"&gt;'&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;span class="nx"&gt;TARGET_TABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Target Table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;TARGET_TABLE_SOURCE_ROW_COLUMN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Source Row URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;oneWaySync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;SOURCE_TABLES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;syncSpecificTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TARGET_TABLE&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;If we look back at our project tasks table, you most likely have one “master” list of tasks, one “master” list of team members, and want to sync those to individual tables in the target doc. The script assumes you have multiple project tasks table that you want to combine into one table in your target doc:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zsx3IfEq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6mzTeKfIiZ51u1r-j9QcOg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zsx3IfEq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6mzTeKfIiZ51u1r-j9QcOg.png" alt=""&gt;&lt;/a&gt;Sync multiple source tables to one target table&lt;/p&gt;

&lt;p&gt;I argue that this is not the most common pattern in the Coda docs you’re looking to sync. Something I see with a lot of our users is this pattern:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZiPnWNrD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AoFJHZaCIqTRuXT6CPp_6ZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZiPnWNrD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AoFJHZaCIqTRuXT6CPp_6ZA.png" alt=""&gt;&lt;/a&gt;Sync tables one-to-one&lt;/p&gt;

&lt;p&gt;In order to do this, we have to edit the script slightly to account for multiple source tables and multiple target tables. I didn’t want to change the data structure needed for the &lt;code&gt;syncSpecificTable()&lt;/code&gt; function, so instead created an array of arrays of &lt;code&gt;doc&lt;/code&gt; and &lt;code&gt;table&lt;/code&gt; key-value pairs so that the &lt;code&gt;oneWaySync()&lt;/code&gt; function can loop through each element in the array and reference the source &lt;code&gt;doc&lt;/code&gt; and &lt;code&gt;table&lt;/code&gt; via the 1st element and the target &lt;code&gt;doc&lt;/code&gt; and &lt;code&gt;table&lt;/code&gt; via the 2nd element. In the script below, &lt;code&gt;table[0]&lt;/code&gt; and &lt;code&gt;table[1]&lt;/code&gt; represent these elements:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;SOURCE_DOC_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;TARGET_DOC_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;TABLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  

  &lt;span class="c1"&gt;//1st table to sync&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SOURCE_DOC_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//1st table from source doc&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TARGET_DOC_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//1st table from target doc&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="c1"&gt;//2nd table to sync&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SOURCE_DOC_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//2nd table from source doc&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TARGET_DOC_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TO UPDATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//2nd table from target doc&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;oneWaySync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;TABLES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;syncSpecificTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;This may not be the most efficient or prettiest way of setting up multiple tables to sync, but it works :).&lt;/p&gt;
&lt;h3&gt;
  
  
  #2 Deleting rows in the source table should delete rows in the target table
&lt;/h3&gt;

&lt;p&gt;If you delete rows of data in the source table, wouldn’t you want the rows to also get deleted in the target table? One way I’ve seen this being done in current data syncs between Coda docs is &lt;a href="https://help.coda.io/formulas/filtering-your-tables"&gt;setting up a filter&lt;/a&gt; in the target doc so that any rows from the source that are supposed to be “deleted” will just get filtered out from the target doc.&lt;/p&gt;

&lt;p&gt;For instance, here are a bunch of tasks from the source table that are completed and should be “deleted” from the source table. You can apply a filter to the source table so that these rows get filtered out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hU-jTbc2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ac2HOQlypZXurrxfZQxpvQQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hU-jTbc2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ac2HOQlypZXurrxfZQxpvQQ.gif" alt=""&gt;&lt;/a&gt;Filter “completed” rows from your main tasks table in the source doc&lt;/p&gt;

&lt;p&gt;Then, in your target table, you can filter out those same rows that have been marked as “Complete.” You’ll notice that in this target table, I’m only interested in the tasks that are owned by “Adam Davis” (he has 4 tasks in various stages):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--92BiMxNE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADcPgoTh6FM_kNLzB6VQuUQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--92BiMxNE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADcPgoTh6FM_kNLzB6VQuUQ.gif" alt=""&gt;&lt;/a&gt;Filter “completed” tasks in target doc for tasks owned by “Adam Davis”&lt;/p&gt;

&lt;p&gt;This pattern only works if there is value you know you can filter on in the table that would remove rows from your table. In many cases related to project management, the project manager might just delete the row entirely since it’s an irrelevant task, they made a mistake with the data entry, or they just want to reduce the number of rows in the main table. The script currently would not allow for deleting rows. If you have &lt;strong&gt;10 rows&lt;/strong&gt; in the source table, those same &lt;strong&gt;10&lt;/strong&gt;  &lt;strong&gt;rows&lt;/strong&gt; would show up in the target table once the sync happens. If you delete &lt;strong&gt;3 rows&lt;/strong&gt; from the source table, there would still be &lt;strong&gt;10 rows&lt;/strong&gt; in the target table (but only &lt;strong&gt;7 rows&lt;/strong&gt; in the source table).&lt;/p&gt;

&lt;p&gt;In order to delete rows from the target table, we need to utilize two resources available to us in the Coda API:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;deleteRow&lt;/code&gt; &lt;a href="https://coda.io/developers/apis/v1beta1#operation/deleteRow"&gt;method&lt;/a&gt; in the GAS library&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;browserLink&lt;/code&gt; &lt;a href="https://coda.io/developers/apis/v1beta1#operation/resolveBrowserLink"&gt;parameter&lt;/a&gt; which gives us a unique identifier for every row in the source table&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;browserLink&lt;/code&gt; is a super useful identifier for doing the one-way sync because it also gives us the ability update rows if there has been a change in the source table. We call this an &lt;a href="https://coda.io/developers/apis/v1beta1#operation/upsertRows"&gt;UPSERT&lt;/a&gt; when you want to either insert or update a row. In the main &lt;code&gt;syncSpecificTable()&lt;/code&gt; function of our GAS script, I add the following code to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieve all the rows from the target table&lt;/li&gt;
&lt;li&gt;Iterate over all these rows&lt;/li&gt;
&lt;li&gt;Delete rows from the target table &lt;strong&gt;if&lt;/strong&gt; the &lt;code&gt;browserLink&lt;/code&gt; (or in this case, the &lt;code&gt;TARGET_TABLE_SOURCE_ROW_COLUMN&lt;/code&gt;) in the target row does not exist in the rows from the source table
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;targetRows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CodaAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listRows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;useColumnNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;targetRows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;sourceSourceRowURLs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TARGET_TABLE_SOURCE_ROW_COLUMN&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;CodaAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TARGET_DOC_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&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;The &lt;code&gt;sourceSourceRowURLs&lt;/code&gt; variable is an array of all the &lt;code&gt;browserLink&lt;/code&gt;s from the source table.&lt;/p&gt;
&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;A few notes about the final GAS script to sync your tables together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first time you do the sync, you need to create a table in the &lt;strong&gt;target doc&lt;/strong&gt; that contains all the columns you want to sync from the &lt;strong&gt;source doc&lt;/strong&gt; (spelling of the column names must be the same)&lt;/li&gt;
&lt;li&gt;The target table &lt;strong&gt;must contain&lt;/strong&gt; a “source row column.” You’ll see the &lt;code&gt;TARGET_TABLE_SOURCE_ROW_COLUMN&lt;/code&gt; variable which tells you what to call this (“Source Row URL” is used in the script)&lt;/li&gt;
&lt;li&gt;Once you have created the “Source Row URL” in your target table, feel free to hide that column and don’t worry about it ever again&lt;/li&gt;
&lt;li&gt;This syncs tables from &lt;strong&gt;one source doc&lt;/strong&gt; to your target doc. You can easily set up tables from other source docs by changing the variable names in the &lt;code&gt;TABLES&lt;/code&gt; variable&lt;/li&gt;
&lt;li&gt;To sync more tables from your source doc to your target doc, just copy lines 11–21 in the script below and paste it below the “2nd table to sync” to create a 3rd table, 4th table, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h4&gt;
  
  
  Instructions to run script
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Create a new &lt;a href="https://script.google.com/home"&gt;Google Apps Script project&lt;/a&gt; and paste the above script into the editor&lt;/li&gt;
&lt;li&gt;Go to your Coda &lt;a href="https://coda.io/account"&gt;Account Settings&lt;/a&gt;, scroll down to “API Settings,” click “Generate API token,” and copy/paste that token into the &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L2"&gt;line 2&lt;/a&gt; of the script.&lt;/li&gt;
&lt;li&gt;Get the doc IDs from your &lt;strong&gt;source doc&lt;/strong&gt; and &lt;strong&gt;target doc&lt;/strong&gt; and paste them into lines &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L3"&gt;3&lt;/a&gt; and &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L4"&gt;4&lt;/a&gt; (the doc ID is the random string of characters after the _d in the URL of your doc&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3JjCqhn_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/539/1%2AchFJW62brTyx2ITsn4ma0A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3JjCqhn_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/539/1%2AchFJW62brTyx2ITsn4ma0A.png" alt=""&gt;&lt;/a&gt;The Coda doc ID is everything after the “_d”&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the table ID from the &lt;strong&gt;source doc&lt;/strong&gt; and paste it into &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L15"&gt;line 15&lt;/a&gt;, and get the table ID from the &lt;strong&gt;target doc&lt;/strong&gt; and paste it into &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L19"&gt;line 17&lt;/a&gt;. If you have more than one table to sync, you’ll see lines &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L19"&gt;27&lt;/a&gt; and &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L31"&gt;31&lt;/a&gt; to sync that table.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Getting the table ID of a doc
&lt;/h4&gt;

&lt;p&gt;Getting the table IDs is super annoying right now (I plan on building a tool to make this easier). In the meantime, you can use the &lt;code&gt;printDocTables()&lt;/code&gt; helper function in &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L31"&gt;line 100&lt;/a&gt; and replace the &lt;code&gt;TARGET_DOC_ID&lt;/code&gt; in &lt;a href="https://gist.github.com/albertc44/c3d5ebc2a9ec00a28e561ea8e64fc0c5#file-coda_one_way_sync_v2-js-L101"&gt;line 101&lt;/a&gt; with &lt;code&gt;SOURCE_DOC_ID&lt;/code&gt; depending on which doc you’re looking at. Run that function, and check view the Logs in GAS to get the table IDs (the all start with &lt;code&gt;grid-&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8hDGILUa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAE9FDiKW115EA34ojOOeDg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8hDGILUa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAE9FDiKW115EA34ojOOeDg.gif" alt=""&gt;&lt;/a&gt;Retrieve table IDs using the printDocTables() helper function&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages of syncing your Coda tables with GAS
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You can change the ordering of columns in the source table or target table&lt;/li&gt;
&lt;li&gt;You can move the table in the source doc to a different section without affecting the sync&lt;/li&gt;
&lt;li&gt;You can add new columns to the source or target table and create your own formulas that are not affected by the sync&lt;/li&gt;
&lt;li&gt;Every table, row, and column in the &lt;strong&gt;source doc&lt;/strong&gt; has a unique ID, which means you can pinpoint the sync down to a “cell”&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Disadvantages of syncing with GAS
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The sync is not real-time and generally takes a few seconds to finish&lt;/li&gt;
&lt;li&gt;As mentioned earlier, you cannot use the &lt;code&gt;onEdit&lt;/code&gt; &lt;a href="https://developers.google.com/apps-script/guides/triggers/"&gt;Simple Trigger&lt;/a&gt; in GAS like you could in Google Sheets. This means all triggers are time-driven.&lt;/li&gt;
&lt;li&gt;If you accidentally change a column name in the target table, the sync won’t work (&lt;em&gt;you can edit the script to account for column name changes since every column has a unique ID, but the current script doesn’t account for this&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Syncing data between Google Sheets using Google Apps Script
&lt;/h3&gt;

&lt;p&gt;The script for syncing data between your Google Sheets is much shorter (but also comes with a few drawbacks):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Instructions to run the script
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Get the spreadsheet ID of your &lt;strong&gt;source spreadsheet&lt;/strong&gt; and &lt;strong&gt;target spreadsheet&lt;/strong&gt; and paste them into the &lt;code&gt;sourceSpreadsheetID&lt;/code&gt; and &lt;code&gt;targetSpreadsheetID&lt;/code&gt; variables, respectively. This is the ID after the /d/ in any Google Sheets file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ftNveM09--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/715/1%2A29xB38dSffDkDHNZRgQXsQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ftNveM09--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/715/1%2A29xB38dSffDkDHNZRgQXsQ.png" alt=""&gt;&lt;/a&gt;Google Sheets ID is after the “/d/”&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Get the sheet name from the &lt;strong&gt;source spreadsheet&lt;/strong&gt; and &lt;strong&gt;target spreadsheet&lt;/strong&gt; and paste them into the &lt;code&gt;sourceWorksheetName&lt;/code&gt; and &lt;code&gt;targetWorksheetName&lt;/code&gt; variables, respectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Optional) If your data in your &lt;strong&gt;source spreadsheet&lt;/strong&gt; is a &lt;a href="https://support.google.com/docs/answer/63175?co=GENIE.Platform%3DDesktop&amp;amp;hl=en"&gt;named range&lt;/a&gt;, comment out &lt;a href="https://gist.github.com/albertc44/bbae27144db5f1f75b76794d6622b3f9#file-google_sheets_one_way_sync-js-L9"&gt;line 9&lt;/a&gt; and un-comment &lt;a href="https://gist.github.com/albertc44/bbae27144db5f1f75b76794d6622b3f9#file-google_sheets_one_way_sync-js-L11"&gt;line 11&lt;/a&gt; and replace &lt;code&gt;teamBugs&lt;/code&gt; with the name of your named range.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Advantages of syncing your Google Sheets with GAS
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Can you event-driven triggers (like an edit to the &lt;strong&gt;source spreadsheet&lt;/strong&gt; ) that will trigger a sync to the &lt;strong&gt;target spreadsheet&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If you used named ranges, can insert new columns in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; and they will show up in the target spreadsheet&lt;/li&gt;
&lt;li&gt;Data syncs between Google Sheets are generally quicker than syncs between Coda docs&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Disadvantages of syncing your Google Sheets with GAS
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You can’t rename the sheet where your data lives in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; or &lt;strong&gt;target spreadsheet&lt;/strong&gt; ; you also cannot &lt;em&gt;move&lt;/em&gt; your table of data to another sheet&lt;/li&gt;
&lt;li&gt;If you delete rows of data in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; , those rows don’t get deleted in the &lt;strong&gt;target spreadsheet&lt;/strong&gt; &lt;em&gt;unless&lt;/em&gt; you have assigned a &lt;a href="https://support.google.com/docs/answer/63175?co=GENIE.Platform%3DDesktop&amp;amp;hl=en"&gt;named range&lt;/a&gt; to your data in the &lt;strong&gt;source spreadsheet&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your data has to be in cell A1 and there can’t be any “gaps” in the data given the way the &lt;code&gt;getDataRange()&lt;/code&gt; &lt;a href="https://developers.google.com/apps-script/reference/spreadsheet/sheet#getDataRange()"&gt;function&lt;/a&gt; pulls in data&lt;/li&gt;
&lt;li&gt;If you insert new columns of data in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; , any columns you created in the &lt;strong&gt;target spreadsheet&lt;/strong&gt; will be overwritten (e.g. custom formulas you’ve written in columns to the right of the main table that was synced)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GAS copies data from the source and pastes in the target
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M1lqoM2d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A6WPynxrLwMdNirO_" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M1lqoM2d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A6WPynxrLwMdNirO_" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike Coda’s API, there is no native row identifier in Google Sheets. Some people have built &lt;a href="https://yagisanatode.com/2019/02/09/google-apps-script-create-custom-unique-ids-in-google-sheets/"&gt;custom scripts&lt;/a&gt; to generate random IDs. Without the &lt;code&gt;Source Row URL&lt;/code&gt; like we have in Coda, the GAS script essentially copies the values from your source spreadsheet and pastes them into your target spreadsheet. It’s a clean wipe of your target spreadsheet which is not the best solution if you have added columns with custom formulas in your target spreadsheet (see bullet point # from the Disadvantages of syncing your Google Sheets with GAS above).&lt;/p&gt;

&lt;p&gt;While the sync is a bit snappier than the sync using Coda’s API, syncing Google Sheets with GAS is not as precise given the lack of unique identifiers for &lt;em&gt;columns&lt;/em&gt; and &lt;em&gt;rows&lt;/em&gt; in the source and target spreadsheet. You could, of course, write a custom formula that creates a unique identifier, but then you have to “store” that identifier in a hidden column or row in the spreadsheet, or perhaps store it in the GAS script itself.&lt;/p&gt;

&lt;p&gt;In most businesses, the data set is usually growing in the number of rows and columns. If the schema in your source data set in the source spreadsheet is staying fixed (e.g. no new columns will be showing up), then the GAS script for syncing your Google Sheets should be sufficient for your needs. You could get fancy and add the named range to account for new columns showing up in your source spreadsheet. With this solution, however, you can’t add any columns to the target spreadsheet (on the sheet where the data is syncing). Otherwise, your custom columns will be overwritten.&lt;/p&gt;

&lt;p&gt;For example, my “Team Project Tracker” source spreadsheet has a bunch of bugs my team is tracking:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--56VmPz-5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_ArHvdDEO9e4K1YcgcHlog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--56VmPz-5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_ArHvdDEO9e4K1YcgcHlog.png" alt=""&gt;&lt;/a&gt;Source spreadsheet with a bunch of team bugs&lt;/p&gt;

&lt;p&gt;The first time I sync the data to another spreadsheet called “My Stuff,” everything copies over correctly. I decided to create a column called &lt;code&gt;Bug ID Number&lt;/code&gt; in column J where I just take the number from the &lt;code&gt;ID&lt;/code&gt; column using the &lt;code&gt;mid()&lt;/code&gt; function:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---n1XR4nZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AGjGTiXP6g4NkVHMnydafwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---n1XR4nZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AGjGTiXP6g4NkVHMnydafwA.png" alt=""&gt;&lt;/a&gt;Target spreadsheet where I added a custom formula to column J&lt;/p&gt;

&lt;p&gt;Now back in my “Team Project Tracker” spreadsheet, I realized I needed to add a &lt;code&gt;Due Date&lt;/code&gt; column and I insert it after column A, shifting all my columns over by 1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ll-yRqnL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AzjFsl7p4hWb4e1qjtPd6VA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ll-yRqnL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AzjFsl7p4hWb4e1qjtPd6VA.png" alt=""&gt;&lt;/a&gt;I added a new “Due Date” column in column B&lt;/p&gt;

&lt;p&gt;What happens when I run the GAS script again? You guessed it. The original formula I had written in column J in my target spreadsheet (“My Stuff”) gets overwritten by the source spreadsheet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e6MLNODG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A5vHgYLGGnSKXqjzH8_8eXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e6MLNODG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A5vHgYLGGnSKXqjzH8_8eXQ.png" alt=""&gt;&lt;/a&gt;Because of the new “Due Date” column, the original “Bug ID Number” column I created in column J is overwritten :(&lt;/p&gt;

&lt;p&gt;If you are syncing data to a target spreadsheet in Google Sheets, the best practice is to leave that target sheet alone and create new sheets where you are doing Vlookups on that target sheet. This way, you can account for new columns being added to the source spreadsheet that gets synced to your target spreadsheet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syncing data between Google Sheets using formulas
&lt;/h3&gt;

&lt;p&gt;Instead of going through GAS, you can use one of Google Sheets’ &lt;a href="https://support.google.com/docs/answer/3093340?hl=en"&gt;built-in formulas&lt;/a&gt; for syncing data: &lt;code&gt;IMPORTRANGE()&lt;/code&gt;. This is the preferred method for most Google Sheets users who don’t want to get into scripting and is decent solution to do a very basic data sync. The basic syntax is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IMPORTRANGE("Source Spreadsheet URL", "Range")
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If I want to pull in all the tasks from my “Project Team Tasks” spreadsheet into my own Google Sheet, I can write a formula like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BTRIfZPc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AExyEY5_KmvKtrC_O8OpDQA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BTRIfZPc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AExyEY5_KmvKtrC_O8OpDQA.png" alt=""&gt;&lt;/a&gt;Using IMPORTRANGE() to import data&lt;/p&gt;

&lt;p&gt;Now whenever new tasks get added to the “All Team Tasks” sheet, they will show up in the “My Stuff” spreadsheet. Notice how the range is A:J? This is to account for new data being add to the spreadsheet whether it’s more rows or columns. This is a common pattern instead of specifying the exact row number like &lt;code&gt;A1:J100&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Aside from the formula being easy to write, you can easily filter data by introducing the &lt;code&gt;QUERY()&lt;/code&gt; &lt;a href="https://support.google.com/docs/answer/3093343?hl=en"&gt;function&lt;/a&gt;, but this requires a bit of SQL knowledge. For the syncing between Coda docs and Google Sheets using GAS, we have to filter in the &lt;strong&gt;target table&lt;/strong&gt; itself versus filtering the data in the GAS script. You could provide a &lt;code&gt;query&lt;/code&gt; parameter to the Coda API to filter the rows returned, but it’s still limited right now in terms of the number of parameters you provide to the API.&lt;/p&gt;

&lt;p&gt;For instance, here is how you could get a filtered set of rows returned from the “Project Team Tasks” spreadsheet where the “Stage” is “Not Started”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PvAi1QCR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9PBqms1iCX2ELf2JVYOtZw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PvAi1QCR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9PBqms1iCX2ELf2JVYOtZw.png" alt=""&gt;&lt;/a&gt;Using QUERY() with IMPORTRANGE() to retrieve filtered rows from a source spreadsheet&lt;/p&gt;

&lt;p&gt;The annoying thing about using &lt;code&gt;QUERY()&lt;/code&gt; with &lt;code&gt;IMPORTRANGE()&lt;/code&gt; is that you have to know the &lt;em&gt;exact column number&lt;/em&gt; from your source spreadsheet that you want to filter on. In the example above, Col4 represents the “Stage” column from my source spreadsheet that I want to filter on. Just like I did with syncing with GAS, here are some advantages and disadvantages of syncing with &lt;code&gt;IMPORTRANGE()&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages of using IMPORTRANGE() for syncing data between Google Sheets
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;No scripting or coding, can use a built-in formula in Google Sheets&lt;/li&gt;
&lt;li&gt;Can use familiar row and column references (e.g. “A1:B5”) to pinpoint the data you want to sync from your &lt;strong&gt;source&lt;/strong&gt; to &lt;strong&gt;target spreadsheet&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Syncs are quicker compared to GAS&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Disadvantages of using IMPORTRANGE() for syncing data between Google Sheets
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;If you accidentally enter some data in the &lt;strong&gt;target spreadsheet&lt;/strong&gt; where the &lt;code&gt;IMPORTRANGE()&lt;/code&gt; is supposed to sync data, it will break the sync&lt;/li&gt;
&lt;li&gt;Similar to syncing Google Sheets with GAS, you cannot move the table in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; to another sheet or shift the table to the right or left without breaking the sync to the &lt;strong&gt;target spreadsheet&lt;/strong&gt; (unless you use a Named Range)&lt;/li&gt;
&lt;li&gt;Deleting rows in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; won’t delete rows in the &lt;strong&gt;target spreadsheet&lt;/strong&gt; (unless you use a Named Range)&lt;/li&gt;
&lt;li&gt;If you are using a named range and insert new columns of data in the &lt;strong&gt;source spreadsheet&lt;/strong&gt; , and columns you added in your &lt;strong&gt;target spreadsheet&lt;/strong&gt; to the right of the main data will be overwritten&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y3Zk_xTx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AHHDO_2OCb36q6Ghk" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y3Zk_xTx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AHHDO_2OCb36q6Ghk" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’re probably left wondering which of the 3 methods is best for syncing data between your tables. Short answer is that it depends on your use case. The long answer is that it depends on a few factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How precise does you one-way sync need to be?&lt;/li&gt;
&lt;li&gt;Do you want to prevent the end user of the &lt;strong&gt;target spreadsheet&lt;/strong&gt; from creating errors in the sync?&lt;/li&gt;
&lt;li&gt;Will the structure of your data in your &lt;strong&gt;source spreadsheet&lt;/strong&gt; change every day, week, month?&lt;/li&gt;
&lt;li&gt;Do you feel comfortable editing scripts in Google Apps Script?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a high-level, here’s how I would frame the value propositions of each method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coda with Google Apps Script — &lt;/strong&gt; The most precise one-way sync but requires more upfront setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheets with Google Apps Script&lt;/strong&gt;  — More prone to overwriting data, but is a faster sync and easier to setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheets with IMPORTRANGE()&lt;/strong&gt; — More prone to overwriting data and least precise, but easiest to set up for simple use cases&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>productivity</category>
      <category>javascript</category>
      <category>googlesheets</category>
      <category>googleappsscript</category>
    </item>
    <item>
      <title>Future of Work: The Maker Generation</title>
      <dc:creator>Al Chen</dc:creator>
      <pubDate>Wed, 01 May 2019 17:19:22 +0000</pubDate>
      <link>https://dev.to/coda/future-of-work-the-maker-generation-dl2</link>
      <guid>https://dev.to/coda/future-of-work-the-maker-generation-dl2</guid>
      <description>&lt;h3&gt;
  
  
  Future of Work: The “Maker Generation”
&lt;/h3&gt;

&lt;p&gt;You may have heard of the term “&lt;a href="https://en.wikipedia.org/wiki/Maker_culture" rel="noopener noreferrer"&gt;makers&lt;/a&gt;” before. Some of the words and phrases that come to mind may include DIY, robotics, and woodworking. The term has expanded in meaning over the last few years, as the Internet has allowed people to make “digital” products with ease. The Internet has also given rise to virtual communities of makers where individuals can ideate and support each other with their projects. For a deeper dive into maker communities, check out &lt;a href="https://medium.com/@rrhoover/the-rise-of-maker-communities-f76ba5daeb7e" rel="noopener noreferrer"&gt;this post&lt;/a&gt; by Ryan Hoover from Product Hunt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFfaZuKLtKpjmIsSGJuR1sw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFfaZuKLtKpjmIsSGJuR1sw.jpeg"&gt;&lt;/a&gt;April 2019 NYC Maker Me&lt;/p&gt;

&lt;p&gt;These virtual communities symbolize a broader movement: &lt;strong&gt;the maker generation&lt;/strong&gt;. At the April 2019 Maker Meetup in NYC, Shishir Mehrotra (CEO of Coda) discussed the Maker Generation by telling the story of YouTube’s early roots. The audience then heard from individuals who participated in the 2019 Product Hunt &lt;a href="https://www.producthunt.com/makers-festival-2019" rel="noopener noreferrer"&gt;Makers Festival&lt;/a&gt; and learned about the products they have built using Coda. Read below for a recap of the meetup.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Maker Generation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqzybID8mq4e8gAqzXnvS5A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqzybID8mq4e8gAqzXnvS5A.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shishir Mehrotra, CEO of Coda, kicked off the meetup by talking about his experience at YouTube. He told a story about his friend &lt;a href="https://en.wikipedia.org/wiki/Sal_Khan" rel="noopener noreferrer"&gt;Sal Khan&lt;/a&gt; and how Sal started &lt;a href="https://www.khanacademy.org/" rel="noopener noreferrer"&gt;Khan Academy&lt;/a&gt; by uploading YouTube videos to help his cousin with algebra since it was hard to coordinate Skype calls. After publishing several videos, Sal’s channel became one of the most watched channels on YouTube. Had he tried “pitching” his idea as a traditional TV program to broadcast TV producers, he may not had the success he has today with reaching millions of people around the world.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the video industry (YouTube), I’ve seen this phenomenon of regular people becoming creators. The same phenomenon is happening to all types of industries such as crafts, gaming, and soon software.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;YouTube is the result of creators democratizing the production of video content. As Shishir’s quote above states, this is not just about video. The same thing is happening to products and crafts with the rise of communities like Etsy where anyone can create and sell their physical goods. Gamers playing Fortnite and Minecraft can create their own worlds to play in. With software, non-coders and non-programmers will be able to build the applications that mold to their workflows.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/poxqG6DxSCA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Makers Festival Submission: CommSponsor by Mac and Jacob
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1y2nl0m4Oq3WCKdZqE_Kmw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1y2nl0m4Oq3WCKdZqE_Kmw.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mac and Jacob wanted to prototype and validate an idea for CommSponsor, a platform that connects great communities on Slack, Discord, and Telegram with great companies.&lt;/p&gt;

&lt;p&gt;The idea started when Jacob realized finding sponsors for his community of data scientists is not an easy task. Instead of writing code to create CommSponsor, Mac and Jacob prototyped a version of the platform in Coda for Product Hunt’s Makers Festival, and turned CommSponsor into a real business 4 weeks later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We went for idea, to prototype, to market validation in under 24 hours using Coda, Carrd, Typeform, and Zapier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/poxqG6DxSCA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;See Mac and Jacob’s slides from the meetup&lt;/em&gt; &lt;a href="https://docs.google.com/presentation/d/1J1O_jfRC1O8-az8VOolLHsFs2Ryxiq0-kYvz0C2ynks/edit#slide=id.p" rel="noopener noreferrer"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and their original&lt;/em&gt; &lt;a href="https://coda.io/d/CommSponsor_dZGpGGWjZ3Z/For-Companies_su5zl#_luvxv" rel="noopener noreferrer"&gt;&lt;em&gt;Coda doc&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for the Makers Festival.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Makers Festival Submission: Cheesy Spanish Love Phrases by Jonathan
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApbKQg_4qRPQCiCLAVc36yg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApbKQg_4qRPQCiCLAVc36yg.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;“Happy wife, happy life.”&lt;/p&gt;

&lt;p&gt;Those were the words Jonathan ended his presentation with as he discussed his submission for the Makers Festival. He scraped lists of love phrases and put them in a Google Sheet to translate them into Spanish. He then put the quotes into Coda. With that, the &lt;em&gt;Cheesy Spanish Love Quotes Generator&lt;/em&gt; doc was launched. In addition to generating cheesy Spanish languages on the fly, Jonathan created buttons in his doc to share the phrases easily on social media and Whatsapp.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I built a basic little app in less than the time for an average commute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/poxqG6DxSCA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here is Jonathan’s&lt;/em&gt; &lt;a href="https://docs.google.com/presentation/d/1eJboz627bKyqVfpXlf5W3vrqV4wrXr-zpX7aHayf6ho/edit#slide=id.g175e307a0_00" rel="noopener noreferrer"&gt;&lt;em&gt;presentation&lt;/em&gt;&lt;/a&gt; &lt;em&gt;from the meetup, and his&lt;/em&gt; &lt;a href="https://coda.io/d/Cheesy-Spanish-Love-Quote-Generator_dvLpHrtESLx/Quote-Generator_suGkY#_lu8TK" rel="noopener noreferrer"&gt;&lt;em&gt;Cheesy Spanish Love Quote Generator Coda&lt;/em&gt;&lt;/a&gt;_ doc._&lt;/p&gt;




</description>
      <category>makers</category>
      <category>meetup</category>
      <category>coda</category>
      <category>producthunt</category>
    </item>
  </channel>
</rss>
