Dynamic API
Comping

Content Strategy, workflows managed with easy to use/moderated spreadsheet tools. Entitlement and access can be easily updated without capital costs or exposure to single point of failure, database breach.

Update UI/UX from Google Sheets/JSON with VUE. API can be inline or global. Styles can be scoped or global. Code can be inserted anywhere (WordPress, Drupal, Any E Commerce, Sync to Webflow live prototyping/Collection API). Google Sheets can port to secure databases with Mutation / GraphQL strategy.

Private Sheets can be commented with collaborative teams, and or secure ETL strategy. Middleware and data cleansing/validations can occur at Sheet Level.

API strategies can be used as components split and loaded in config management in Nuxt. Both server and client rendering are supported. SEO/Context Meta information is stored with built in State Management. Nuxt has prebuilt, data stores, routing, seo, config, .env configuration. Fetch can be done with fetch calls or Axios.

Use to prototype data feed strategies. Shopify, WordPress, Youtube, Buzzsprout, Google Maps, Google Docs, Mailchimp, Klaviyo all have APIs that can sync and be styled in Webflow Collections/MVC design strategy. Use Zapier/Integromat to set up the synching.

API usage limits apply (better than Webflow – free to use) 

*This version of the Google Sheets API has a limit of 500 requests per 100 seconds per project, and 100 requests per 100 seconds per user. Limits for reads and writes are tracked separately. There is no daily usage limit.

You can style in Webflow and add CSS to LESS/Sass compile or add to Global Context.

Design your models/schema and design style in Webflow with an auto synced “webhooked” Collection and styling prototyper.

Use this in staging only. Designers can real time design Custom Types. Marketing can update live sheets with IP/Token managed entitlement. 

Clean data is ported to live environments, with non destructive development in place. .env security is included with Netlify (can be Heroku, AWS Lightsail, GH Pages, Google Firebase Deploy) Deployment and GIT based workflows. Use Drupal, WordPress, Mailchimp, YouTube, Shopify (infinite …etc)  as a scalable backend with any API live link required.

QA occurs in staged deployment that is not publically visible.

Google Tables

Use Google Tables with headline TLS managed Databases (Firebase, Mongo), with synced automated and scheduled structured and CLEANED data models.

Automation, data syncing with “legacy” SQL based data with Firewall requirements can be securely managed with token based entitlement.

Build automatic schema and Asset Tags that can filter Assets/Data prior to ETL to back end services.

Forms / Methods can be built into functions/LAMBDAs.

Manage with monitoring and IP based security.

Google Sheets as an API

API conversions

Use Google Sheets to organize Omni Channel Campaigns, Tags, CRMs and Marketing Data.

Use case: Mailchimp, Klaviyo, Air Table (Air Table Base with Shopify) Shopify. 

ACF (Woo Commerce) / Metafields (Shopify)

Use Custom Posts Types and Metafields to Scope and model Schema that can be passed and styled via component IA.

Atomic Design can live load any data that is modeled in secure source with endpoint configuration management utilizing the Global / Scoped / State IA of Nuxt.

Vue and API

Reset Filters

“{{ quote.quote }}”
– {{ quote.author}} ({{ quote.source }})
{{ tag }}
SIDEBAR
<style>
  sidebar .li{
      cursor: pointer;
    }
</style>

<div id="sidebar" class="uk-panel" >

          <div id="reset-filter" v-on:click="reset">
            Reset Filters
          </div>
          
          <div id="authors">
            <div>
              Authors
            </div>
            <ul>
              <li class="uk-list" v-for="author in authors" v-on:click="selectAuthor" :data="author">
                {{ author }}
              </li>
            </ul>
          </div>

          <div id="tags">
            <div>
              Tags
            </div>
            <ul>
              <li class="uk-list" v-for="tag in tags" v-on:click="selectTag" :data="tag">
                {{ tag }}
              </li>
            </ul>
          </div>

        </div>
SEARCHABLE FIELDS
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!--    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+HK&display=swap" rel="stylesheet"> -->
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

    <style>
  
      #header {
        margin: 16px 0px 16px 0px;
      }
      #search {
        padding: 22px 16px 22px 16px;
      }
      .quote {
        margin-bottom: 16px;
        padding: 10px 10px 24px 10px;
        border-bottom: 1px dotted #CECECE;
      }
      .quote-text {
        font-size: 1.2em;
      }
      .author {
        margin-left: 24px;
        font-weight: bold;
        color: #676767;
      }
      .source {
        font-size: 0.8em;
        color: #676767;
      }
      .tag-container {
        text-align: right;
      }
      .tag {
        border-radius: 12px;
        background-color: #17A2B8;
        color: #FFFFFF;
        padding: 5px 10px 10px ;
        margin-left: 5px;
        font-size: 0.8em;
       
      }

      #sidebar {
        padding: 12px;
      }

      .menu-item {
        cursor: pointer;
      }
      .menu-item:hover {
        color: #4477AA;
      }
      #reset-filter {
        cursor: pointer;
        margin-bottom: 24px;
      
      }
      #reset-filter:hover {
        color: #4477AA;
      }
    </style>


    <div id="app">
    </div>
      
    <div id="content" class="uk-section">


        
        
      <div id="header" >
        <input class="uk-input"
          id="search"
          v-on:input="filterQuotes"
          type="search"
          placeholder="Search Quotes"
          class="form-control bg-none border-1">
      </div>

      <div class="uk-panel">

        <div id="quotes" class="uk-card">
          <div v-for="quote in quotes" class="quote">
            <div class="quote-text">"{{ quote.quote }}"</div>
            <div>
              <span class="author">- {{ quote.author}}</span>
              <span class="source" v-if="quote.source != ''">({{ quote.source }})</span>
            </div>
            <div class="tag-container">
              <span v-for="tag in quote.tags" class="tag">
                {{ tag }}
              </span>
            </div>
          </div>
        </div>

       

      </div>

    </div>

    <script>
      // URL to the JSON data of the Google Spreadsheet
      var gsheet_url = "https://spreadsheets.google.com/feeds/list/1eNmGC4mZpIGx9vyL_Y0m0wEvsnlREGYoj04LH9atoTg/1/public/values?alt=json";
      
      // Global variables to hold the data from the spreadsheet
      var quoteList = [];
      var authorList = [];
      var tagList = [];
      
      // Load data when the page is ready
      var app = new Vue({
        el: '#app',
        data () {
          return {
            info: null
          }
        },
        mounted () {
          axios
            .get(gsheet_url)
            .then(response => (
              parseData(response.data.feed.entry)
            ))
        }
      });

      // Search bar
      var search = new Vue({
        el: '#search',
        methods: {
          filterQuotes: function(event) {
            var query = event.target.value;

            // Reset filter if query is empty string
            if (query.length == 0) {
              quotes.quotes = quoteList;
            }

            // Do nothing if query is too short
            if (query.length < 3) return;
            
            var filtered = [];
            query = query.toLowerCase();
            console.log(query);

            // Search in quote, author and source
            quoteList.forEach(function(value) {
              var quote = value.quote.toLowerCase();
              var author = value.author.toLowerCase();
              var source = value.source.toLowerCase();
              if (
                (quote.search(query) >= 0) ||
                (author.search(query) >= 0) ||
                (source.search(query) >= 0)) {
                filtered.push(value);
              }
            });
            quotes.quotes = filtered;
          }
        }
      });

      var quotes = new Vue({
        el: '#quotes',
        data: {
          quotes: quoteList
        }
      });

      var authors = new Vue({
        el: '#authors',
        data: {
          authors: authorList
        },
        methods: {
          selectAuthor: function(event) {
            var selected = [];
            var author = event.target.getAttribute('data');
            quoteList.forEach(function(value) {
              if (value.author == author) {
                selected.push(value);
              }
            });
            quotes.quotes = selected;
          }
        }
      });

      var resetFilter = new Vue({
        el: '#reset-filter',
        methods: {
          reset: function(event) {
            quotes.quotes = quoteList;
          }
        }
      });

      var tags = new Vue({
        el: '#tags',
        data: {
          tags: tagList
        },
        methods: {
          selectTag: function(event) {
            var selected = [];
            var tag = event.target.getAttribute('data');
            quoteList.forEach(function(value) {
              if (value.tags.includes(tag)) {
                selected.push(value);
              }
            });
            quotes.quotes = selected;
          }
        }
      });

      function parseData(entries) {
        
        var authorSet = new Set();
        var tagSet = new Set();

        entries.forEach(function(value) {
          var entry = {
            "quote": value.gsx$quote.$t,
            "author": value.gsx$author.$t,
            "source": value.gsx$source.$t,
            "tags": value.gsx$tags.$t.split(",")
          };
          authorSet.add(entry.author);

          entry.tags.forEach(function(t) {
            tagSet.add(t);
          });

          quoteList.push(entry);
        });
        authorList = Array.from(authorSet);
        authorList.sort();

        tagList = Array.from(tagSet);
        tagList.sort();

        quotes.quotes = quoteList;
        authors.authors = authorList;
        tags.tags = tagList;
      }

    </script>


Original Git Source

https://github.com/albertauyeung/quotes-app/blob/master/index.html

© 2020 All rights reserved. Powered by Yoonsun Lee.