{"componentChunkName":"component---src-templates-page-tsx","path":"/page/7","result":{"pageContext":{"searchData":[{"id":"cjjg9ui0t303s010375m42b9w","title":"Turn a Browser Window into a Notepad with This One-Liner","slug":"/turn-a-browser-window-into-a-notepad-with-this-one-liner","avatar":"https://s3.amazonaws.com/contentkit/static/cjjg9ui0t303s010375m42b9w/OYIaJ1KK_400x400(1).png","date":"July 1, 2020"},{"id":"cjiy7xl9o17w701039gvl18a5","title":"Creating a Collaborative Editor with Draftjs for Fun","slug":"/draft-js-collaborative-editor","avatar":"https://s3.amazonaws.com/contentkit/static/cjiy7xl9o17w701039gvl18a5/draft-js.png","date":"June 28, 2020"},{"id":"cjeqgfsdsnmx90167n7j290kt","title":"How To Include SASS In Your React Project","slug":"/sass-react-webpack","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfsdsnmx90167n7j290kt/parcel-bundler.png","date":"May 1, 2020"},{"id":"cjiy4tseq0tnw0103bc5s7sxj","title":"How to Add a Loading Indicator to Material Ui's Component","slug":"/creating-a-material-ui-button-with-spinner-that-reflects-loading-state","avatar":"https://s3.amazonaws.com/contentkit/static/cjiy4tseq0tnw0103bc5s7sxj/material-ui.png","date":"January 28, 2020"},{"id":"cjkq4u7470ihr0157ad175b12","title":"Connecting to AWS Lambda via WebSockets","slug":"/connecting-to-aws-lambda-via-websockets","avatar":"https://s3.amazonaws.com/contentkit/static/cjkq4u7470ihr0157ad175b12/MQTT.js.png","date":"January 12, 2020"},{"id":"cjeqgfnhknnpe0199zbfwwkd8","title":"6 Really Cool APIs to Have Fun With","slug":"/cool-apis-to-have-fun-with","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfnhknnpe0199zbfwwkd8/scale-api.png","date":"January 1, 2020"},{"id":"cjeqgftvknnr30199dvw266qh","title":"Installing Node Canvas in AWS Lambda","slug":"/node-canvas-aws-lambda","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgftvknnr30199dvw266qh/aws-lambda.jpg","date":"December 31, 2019"},{"id":"cjn5fv8kl0pfj0124wwebufms","title":"GoLang Cheatsheet","slug":"/golang-cheatsheet","avatar":"https://s3.amazonaws.com/contentkit/static/cjn5fv8kl0pfj0124wwebufms/golang.png","date":"October 13, 2019"},{"id":"cjn15y8740liw0175u3s707eh","title":"Scheduled Jobs & Work Queues With Postgresql","slug":"/scheduled-jobs-work-queues-with-postgresql","avatar":"https://s3.amazonaws.com/contentkit/static/cjn15y8740liw0175u3s707eh/kxHkAenZ_400x400.jpg","date":"October 8, 2019"},{"id":"cjmym86fh0jy1013398nfzuqu","title":"Creating a Bot to Refill Parking Meters Using AWS Lambda","slug":"/creating-a-bot-to-refill-parking-meters-using-aws-lambda","avatar":"https://s3.amazonaws.com/contentkit/static/cjmym86fh0jy1013398nfzuqu/prwHMlRn_400x400.jpg","date":"October 7, 2019"},{"id":"cjmsaqt6l09le01046qeukpp9","title":"The USPS Tracking API: How To Track Packages","slug":"/usps-tracking-api","avatar":"https://s3.amazonaws.com/contentkit/static/cjmsaqt6l09le01046qeukpp9/usps.png","date":"October 3, 2019"},{"id":"cjeqgfuyenmy20167rycnmiql","title":"Stormpath vs Firebase - A Side-By-Side Comparison","slug":"/stormpath-vs-firebase-a-side-by-side-comparison","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfuyenmy20167rycnmiql/m3cEA33V_400x400.jpg","date":"September 2, 2019"},{"id":"cjeqgfv88nnrt01997wxd4rnl","title":"Sending emails with Firebase Cloud Functions","slug":"/firebase-functions-sending-emails","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfv88nnrt01997wxd4rnl/firebase.jpg","date":"September 2, 2019"},{"id":"cjeqgfqjknnq20199oe3zwi37","title":"Deploying To DigitalOcean From Travis","slug":"/deploying-to-digitalocean-travis","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfqjknnq20199oe3zwi37/digitalocean.jpeg","date":"August 25, 2019"},{"id":"cjkvpbr6p06z50181fg7xvsc3","title":"Circumventing AWS Lambda's Bundle Size Limit","slug":"/circumventing-aws-lambdas-bundle-size-limit","avatar":"https://s3.amazonaws.com/contentkit/static/cjkvpbr6p06z50181fg7xvsc3/b2lWK7c0_400x400.png","date":"August 15, 2019"},{"id":"cjiy45h7m0iba0111f5imt5em","title":"A Quick Way to List All Unicode Characters (Javascript)","slug":"/unicode-characters-javascript","avatar":"https://s3.amazonaws.com/contentkit/static/cjiy45h7m0iba0111f5imt5em/unicode.png","date":"July 29, 2019"},{"id":"ci1rxc41tm8yi7nd156pz9dom","title":"Kibana Rest API","slug":"/kibana-rest-api","avatar":"https://s3.amazonaws.com/contentkit/static/ci1rxc41tm8yi7nd156pz9dom/elastic.png","date":"July 24, 2019"},{"id":"cjeqgfjgennmw0199wha3j6u0","title":"Airtable As A Database For Middleman [Tutorial]","slug":"/airtable-middleman-database","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfjgennmw0199wha3j6u0/airtable-books.png","date":"June 1, 2019"},{"id":"cjeqgfj5qnnmr0199vzd85xuo","title":"Building A Multiplayer Game With Three.Js + WebSockets","slug":"/multiplayer-game-threejs","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfj5qnnmr0199vzd85xuo/three.jpg","date":"June 1, 2019"},{"id":"cjeqgfi8hnnml0199f1jyo1p5","title":"The Best Sketch Plugins","slug":"/the-best-sketch-plugins","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfi8hnnml0199f1jyo1p5/sketch.png","date":"June 1, 2019"},{"id":"d9920hsu8y7365frf2c6fxrx2","title":"Configuring Vault by Hashicorp in AWS EC2","slug":"/configuring-vault-by-hashicorp-in-aws-ec2","avatar":"https://s3.amazonaws.com/contentkit/static/d9920hsu8y7365frf2c6fxrx2/vault.png","date":"April 15, 2019"},{"id":"cjeqgfvsfnns00199mlbff48i","title":"Best Zapier Alternatives","slug":"/best-zapier-alternatives","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfvsfnns00199mlbff48i/zapier-alternative-workato.png","date":"January 31, 2019"},{"id":"cjn3l18390lyt0158i8qxs5dc","title":"Running A Simple Node Web Server On AWS EC2","slug":"/running-a-simple-node-web-server-on-aws-ec2","avatar":"https://s3.amazonaws.com/contentkit/static/cjn3l18390lyt0158i8qxs5dc/aws.png","date":"October 11, 2018"},{"id":"cjeqgfr4snmwz01673m8l4i51","title":"Graph.Cool vs Firebase","slug":"/graphcool-vs-firebase","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfr4snmwz01673m8l4i51/graphcool.png","date":"October 7, 2018"},{"id":"cjklurup00k0201739mflg9sz","title":"Accessing Redis on an Aws EC2 Instance from the Outside\t","slug":"/accessing-redis-on-an-aws-ec2-instance-from-the-outside","avatar":"https://s3.amazonaws.com/contentkit/static/cjklurup00k0201739mflg9sz/logo.jpeg","date":"August 9, 2018"},{"id":"cjkfzvvxt08up0191l38aadq4","title":"Using PDFtk in AWS Lamba","slug":"/using-pdftk-in-aws-lamba","avatar":"https://s3.amazonaws.com/contentkit/static/cjkfzvvxt08up0191l38aadq4/pdftk.png","date":"August 4, 2018"},{"id":"cjeqgfqsgnnq70199l4vc6vim","title":"Configuring WebSockets on Elastic Beanstalk/EC2","slug":"/websockets-aws-elasticbeanstalk-ec2","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfqsgnnq70199l4vc6vim/aws.png","date":"July 15, 2018"},{"id":"cjit96q2yk0is0111qpbmw66s","title":"Getting Started With Gmail API","slug":"/gmail-api-quickstart","avatar":"https://s3.amazonaws.com/contentkit/static/cjit96q2yk0is0111qpbmw66s/gmail.png","date":"June 28, 2018"},{"id":"cjeqgfo23nmwd0167ynqe7xi8","title":"5 Tips For Using NextJs","slug":"/5-tips-for-using-nextjs","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfo23nmwd0167ynqe7xi8/bHjpwZem_400x400.png","date":"June 1, 2018"},{"id":"cjhxixcyhw4ze01035butoukz","title":"React unstable_deferredUpdates","slug":"/react-unstable_deferredupdates","avatar":"https://s3.amazonaws.com/contentkit/static/cjhxixcyhw4ze01035butoukz/OYIaJ1KK_400x400(1).png","date":"June 1, 2018"},{"id":"cjeqgflpnnnoy01993y7aez8a","title":"Simple Web Scraping With Javascript","slug":"/simple-web-scraping","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgflpnnnoy01993y7aez8a/developer-tools-scraping.png","date":"May 1, 2018"},{"id":"cjeqgfk9lnnn101994ll4ursr","title":"Easy: Add Firebase Facebook Login To Your React App","slug":"/firebase-facebook-login-react","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfk9lnnn101994ll4ursr/firebase.png","date":"May 1, 2018"},{"id":"cjeqgfiqrnmtj0167dmz5g5dg","title":"The 5 Best Static Site Web Hosts","slug":"/the-5-best-static-site-web-hosts","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfiqrnmtj0167dmz5g5dg/digital-ocean.png","date":"May 1, 2018"},{"id":"cjeqgfmi2nmvs01670pgebekn","title":"Tips and Tricks For Using NightmareJs","slug":"/nightmare-js","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfmi2nmvs01670pgebekn/nightmare.png","date":"May 1, 2018"},{"id":"cjeqgfkqennn60199707yp1fb","title":"Why You Should Create Your Next React Web App With Firebase","slug":"/firebase-react-tutorial","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfkqennn60199707yp1fb/firebase.jpg","date":"May 1, 2018"},{"id":"cjeqgfpr6nnpx019978qzmaok","title":"How to Flush Data From Heroku Redis","slug":"/heroku-redis-flushall","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfpr6nnpx019978qzmaok/3wgIDj3j_400x400.png","date":"April 1, 2018"},{"id":"cjeqgfm8xnnp30199vxndhkgh","title":"5 Ways To Style React Components","slug":"/5-ways-to-style-react-components","avatar":null,"date":"April 1, 2018"},{"id":"cjeqgflz7nmvm0167yo7wsjg3","title":"Delete Spreadsheet Rows For Google Sheets","slug":"/delete-rows-google-sheets","avatar":null,"date":"April 1, 2018"},{"id":"cjeqgfp84nnps0199dvru09ll","title":"Make An Uptime Monitoring Microservice In Under 50 Lines of Code","slug":"/twilio-uptime-monitoring-node-tutorial","avatar":null,"date":"April 1, 2018"},{"id":"cjeqgfri4nnqd0199zsv6a9fl","title":"Hexo - The Best Static Site Generator? ","slug":"/deploy-a-hexo-blog","avatar":null,"date":"April 1, 2018"},{"id":"cjeqgfoygnnpn0199f31dgk9m","title":"Airtable As A Minimum Viable Database For Your ReactJs Project","slug":"/airtable-reactjs","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfoygnnpn0199f31dgk9m/airtable-screenshot.png","date":"March 2, 2018"},{"id":"cjeqgfn6pnmw0016793f81hpx","title":"The Advanced Guide To ReactJs Checkboxes","slug":"/reactjs-checkboxes","avatar":null,"date":"January 20, 2018"},{"id":"cjeqgfe8znnly01991jo5xkxx","title":"Minimum Viable GraphQL QuickStart","slug":"/minimum-viable-graphql-quickstart","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfe8znnly01991jo5xkxx/graphcool-schema.png","date":"January 1, 2018"},{"id":"cjeqgfgegnnmb0199jp3hv2xx","title":"How To Add A Contact Form To Your Ghost Blog","slug":"/ghost-blog-contact-form","avatar":null,"date":"November 1, 2017"},{"id":"cjeqgfmvxnnp90199bdti4r8n","title":"PHP Scraping Tutorial - Scrape Reddit With Goutte","slug":"/php-scraping-tutorial-scrape-reddit-with-goutte","avatar":null,"date":"October 7, 2017"},{"id":"cjeqgfpz1nmwp0167c5j46eij","title":"Cannot read property 'loose' of undefined","slug":"/cannot-read-property-loose-of-undefined","avatar":null,"date":"August 25, 2017"},{"id":"cjeqgftlanmxg0167zipvfzp1","title":"Airtable API Example & Tutorial - Generating Charts","slug":"/airtable-api-example-tutorial","avatar":null,"date":"January 31, 2017"},{"id":"cjeqgfphbnmwk0167ldz2mv2q","title":"React onClick Example and Tutorial","slug":"/react-onclick-example-and-tutorial","avatar":null,"date":"January 2, 2017"},{"id":"cjeqgfq8ynmwu0167z6c51ynp","title":"React Tables - How To Render Tables In ReactJS","slug":"/reactjs-tables","avatar":null,"date":"January 2, 2017"},{"id":"cjeqgfuoznmxu0167ayt2zkc3","title":"How To Add A Class in ReactJS","slug":"/reactjs-add-class","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgfu6gnnrb0199nyrddra0","title":"Fetching Github Blame with the GraphQL API V4","slug":"/github-blame-graphql-api-v4","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgfsmsnnqo0199o2x7dl4x","title":"How To Add Meta Descriptions to Middleman Pages","slug":"/middleman-meta-descriptions","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgfs2wnnqi0199rco2vvz2","title":"Zapier Webhook Post Example & Tutorial","slug":"/zapier-webhook-post-example-tutorial","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgfvhunmy90167t6ouqfmb","title":"Setting Up A Job Queue For A Node App [Tutorial]","slug":"/job-queue-node","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgftbcnnqy0199nc1f92te","title":"NextJs vs Create-React-App - A Side-By-Side Comparison","slug":"/nextjs-vs-create-react-app","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgft2pnnqt01990ty8fmeu","title":"How To Create A Modal In ReactJS [Tutorial]","slug":"/reactjs-modal","avatar":null,"date":"March 14, 2018"},{"id":"cjeqgfugpnnrj0199x7anb33t","title":"How To Use Twilio With ReactJS","slug":"/reactjs-twilio-example-tutorial","avatar":null,"date":"March 14, 2018"}],"page":7,"offset":35,"total":57,"nodes":[{"id":"cjeqgfpr6nnpx019978qzmaok","title":"How to Flush Data From Heroku Redis","slug":"heroku-redis-flushall","published_at":"2018-04-01T20:42:24.526","created_at":"2018-03-14T02:16:38","excerpt":null,"image":{"id":"hj24catmxk7w4r9ib47r5roa3","url":"static/cjeqgfpr6nnpx019978qzmaok/3wgIDj3j_400x400.png"},"posts_tags":[{"tag":{"id":"5276cfewytt6smbp4sc2","name":"Redis"}},{"tag":{"id":"7h26a6rn650rhht8vooq","name":"Heroku"}}],"date":"April 1, 2018","html":"\n
Locally, you could flush a redis database with the following:
\nredis-cli\nFLUSHALL
\nHow can you accomplish the same on Heroku Redis? Here's how:
\nheroku redis:cli -a my_app --confirm my_app\nFLUSHALL
\nEven better, here's a one-liner:
\necho \" FLUSHALL\\r\\n QUIT\" | heroku redis:cli -a MY_APP --confirm MY_APP
","avatar":"https://s3.amazonaws.com/contentkit/static/cjeqgfpr6nnpx019978qzmaok/3wgIDj3j_400x400.png"},{"id":"cjeqgfm8xnnp30199vxndhkgh","title":"5 Ways To Style React Components","slug":"5-ways-to-style-react-components","published_at":"2018-04-01T16:00:00","created_at":"2018-03-14T02:16:33","excerpt":"The chaos (or inventiveness) of the javascript ecosystem is reflected in all the choice you have to","image":null,"posts_tags":[],"date":"April 1, 2018","html":"The chaos (or inventiveness) of the javascript ecosystem is reflected in all the choice you have to style React components.
\nIn this post I'll discuss some of the approaches you can take to style React components.
\nFrom the 2016 StateOfJs survey, we learned:
\nLooking at the result of the survey, it seems both SASS and Plain CSS are used by developers at the same level. But looking at the satisfaction rate, it turns out that developers who use SASS and CSS Modules are more satisfied with them compared to the other options.\n
Although it might seem like Plain CSS comes out on top, we find something interesting when we look at the correlation values of the heatmap.\n
According to the chart, there's a strong correlation between using plain CSS and not using a JavaScript framework for your client-side code; and conversely, using SASS means you're more likely to also use a front-end frameworks.\n
This is the default CSS-in-js approach that is baked into React. You pass an object with camelcased styles to your React component:
\n<div styles={{ color: \"red\" }}>red</div>
\nThis approach fits with the modularity of components. Let's say you have a button.js component. If you're only using inline styles then all your styling will be found in one place (or close by).
\nconst styles = {\n backgroundColor: \"#f8f8f8\",\n border: \"1px solid #dd\",\n padding: \"8px 16px\"\n};\nconst Btn = () => (\n <button style={styles}>Click me!</button>\n)
\nAdvantages:
\nDisadvantages
\nThe main reason I don't use this approach is because I prefer to write plain ole' css and it results in a lot of duplicated styling.
\nYou can also import a regular stylesheet.
\nIf you're using Webpack, you can include the css file in a React container component by installing style-loader and css-loader:
\nnpm i style-loader css-loader --save-dev
\nNext add this to the loaders section of your Webpack config file:
\nmodule: {\n rules: [{\n test: /\\.css$/,\n use: [\n 'style-loader',\n 'css-loader'\n ]\n }]\n}
\nFinally require the css in the entry point to your app:
\nimport './style.css';
\nAdvantages:
\nDisadvantages
\nStyled components is pretty nifty. To get started:
\nnpm i styled-components --save-dev
\nAnd here's how you use it.
\nimport React from 'react';\nimport styled from 'styled-components';\nconst Btn = styled.button`\n background-color: #f8f8f8;\n border: 1px solid #dd;\n padding: 8px 16px;\n`;\nclass App extends React.Component {\n render() {\n return(\n <div>\n <Btn />\n </div>\n );\n }\n}
\nStyled components lets you write traditional css write in your js files. You keep the style logic in javascript but still write conventional css (background-color: #f9f9f9 instead of { backgroundColor: '#f9f9f9' }).
\nStyled-components also makes it easer to import default styles and then modify them. This cuts down on the style duplication the traditional inline styles approach is vulnerable to.
\nYou can pass props with styled-components to handle logic:
\nconst Button = styled.button`\n /* If it's a small button use less padding */\n padding: ${props => props.small ? '0.25em 1em' : '0.5em 2em'};\n /* …more styles here… */\n`;\nconst App = () => (\n <Button small={true}>\n)
\nAnd manipulate styles based on device:
\nimport { css, styled } from 'styled-components'\nexport const media = {\n handheld: (...args) => css`\n @media (max-width: 420px) {\n ${ css(...args) }\n }\n `\n}\n// Make the text smaller on handheld devices\nconst Box = styled.div`\n font-size: 16px;\n ${ media.handheld`\n font-size: 14px;\n ` }\n`;
\nAphrodite is a clean way to write CSS in JavaScript and embed styles in individual UI components.
\nimport React from 'react';\nimport { StyleSheet, css } from 'aphrodite';\nconst styles = StyleSheet.create({\n red: {\n backgroundColor: 'red'\n }\n});\nconst App = () => (\n <span className={css(styles.red)}>\n This is red.\n </span>\n)
\nI don't think this is the best option, but I've used styled-jsx along with nextjs to style React components.
\nconst RedText = () => (\n <div>\n <p>only this paragraph will get the style :)</p>\n { /* you can include <Component />s here that include\n other <p>s that don't get unexpected styles! */ }\n <style jsx>{`\n p {\n color: red;\n }\n `}</style>\n </div>\n)
\n�
\nThis product is a simple add on for Google Sheets that allows you to delete rows in bulk according to specified criteria.
\nPlease contact support@automationfuel.com for help.
\nNote that this product is for use with Google Sheets but was not developed by Google. AutomationFuel is not affiliated with Google.
\nYou can download this add on from the Google Play Store.
\nOnce installed, to use the add on, please navigate to the spreadsheet you wish to manipulate.
\nAfter opening your Google Sheet click the Addons menu. Next, go to \"Google Sheets Delete Rows\" => Quick Start. Enter the value for the rows you’d like to delete. For example, if you enter \"foo\" rows with this exact value will be removed but rows with the value \"foo bar\" will be spared.
\nAt this stage, you can exit the sidebar without deleting anything if you chose by clicking \"Close sidebar\" at the bottom of the sidebar.
\nIf you wish to undo any deletions, you can use the shortcut command-Z.
","avatar":null},{"id":"cjeqgfp84nnps0199dvru09ll","title":"Make An Uptime Monitoring Microservice In Under 50 Lines of Code","slug":"twilio-uptime-monitoring-node-tutorial","published_at":"2018-04-01T16:00:00","created_at":"2018-03-14T02:16:37","excerpt":"Wouldn't it be nice to get a text message if one of your websites is down? In this tutorial, I'll s","image":null,"posts_tags":[],"date":"April 1, 2018","html":"Wouldn't it be nice to get a text message if one of your websites is down? In this tutorial, I'll show you how to build a minimum viable uptime monitoring service.
\n\ngit clone https://github.com/unshift/uptime-monitoring.git\ncd uptime-monitoring\nnpm install
\nEdit .env:
\nTWILIO_ACCOUNT_SID={YOUR TWILIO ACCOUNT SID}\nTWILIO_AUTH_TOKEN={YOUR TWILIO AUTH TOKEN}\nTWILIO_NUMBER={YOUR TWILIO REGISTERED NUMBER}\nRECIPIENT_NUMBER={YOUR NUMBER}
\ncd uptime-monitoring\nheroku create\nheroku buildpacks:set https://github.com/heroku/heroku-buildpack-nodejs#v107
\nheroku config:set TWILIO_ACCOUNT_SID={YOUR TWILIO ACCOUNT SID}\nheroku config:set TWILIO_AUTH_TOKEN={YOUR TWILIO AUTH TOKEN}\nheroku config:set TWILIO_NUMBER={YOUR TWILIO REGISTERED NUMBER}\nheroku config:set RECIPIENT_NUMBER={YOUR NUMBER}
\ngit remote -v ## check to make sure you've got the right heroku remote \ngit push heroku master
\nWe'll use Node. I'll assume that node and npm are installed on your system.
\nLet's start from scratch.
\nmkdir uptime-monitoring && cd uptime-monitoring\nnpm init\ntouch index.js
\nFirst, let's install isomorphic-fetch, twilio, and node-schedule:
\nnpm i twilio isomorphic-fetch node-schedule --save\nWhy these modules?
\nWe'll use:
\nrequire('isomorphic-fetch')\nconst sites = [\n 'http://www.example.com'\n]\nconst run = async () => {\n for(let i in sites) {\n var resp = await fetch(url).catch(err => { return err }) \n if(resp && resp.status >= 200 && resp.status < 300) {\n // Site is OK\n } else {\n // Site is down; send an SMS\n }\n }\n}\nrun() // call run() to test things out
\nThe above snippet makes a fetch request to the URIs in sites.
\nWe'll use async/await syntax, but you could just as well use then.
\nIf you don't want to use a for() loop, you could use this syntax:
\nvar responses = await Promise.all(sites.map(site => {\n // Map needs to be wrapped in Promise.all()\n // Don't forget that await can only be used if the enclosing function is async\n return fetch(site)\n}))
\nFirst, we need to require the twilio node module. Sending an SMS is easy.
\nvar twilio = require('twilio');\nconst accountSid = ''; // from your twilio dashboard\nconst authToken = ''; // from your twilio dashboard\nvar twilioClient = new twilio(accountSid, authToken);\nconst sendMessage = async () => {\n // to is the recipient phone number.\n // from is the number you registered with twilio to send text messages.\n // body is the actual message to send.\n // Note: to and from must be formatted with the country code: +12345678910.\n return await twilioClient.messages.create({body, to, from}) \n}
\nCreate an account at twilio.com. Once you register, you'll see your ACCOUNT SID and AUTH TOKEN in your dashboard. Lastly, you'll need to buy a phone number (the first one is free) to dispatch the text messages.
\n\nWhat we have so far:
\nWe can use node-schedule to execute our function at regular intervals. Node schedule accepts a crontab and a callback as follows:
\nconst schedule = require('node-schedule')\nvar j = schedule.scheduleJob('*/5 * * *', () => {\n // function to execute every 5 minutes\n})
\n\nPutting everything together, we have:
\nconst schedule = require('node-schedule')\nconst twilio = require('twilio')\nrequire('isomorphic-fetch')\nconst sites = ['http://www.example.com']\nconst config = {\n accountSid: '',\n authToken: '',\n twilioNumber: '',\n recipientNumber: ''\n}\nvar twilioClient = new twilio(config.accountSid, config.authToken);\nconst sendMessage = async (site) => {\n return await twilioClient.messages.create({\n body: `${site} is down!`,\n to: config.recipientNumber, \n from: config.twilioNumber\n })\n} \nconst run = async () => {\n for(let i in sites) {\n var resp = await fetch(sites[i]).catch(err => { return err })\n if(resp && resp.status >= 200 && resp.status < 300) {\n // Site is OK\n console.log(`${sites[i]} is OK`)\n } else {\n // Site is down; send an SMS\n var msgResp = await sendMessage(sites[i])\n console.log(`${sites[i]} is Down. SMS status: ${msgResp.status}`)\n }\n }\n}\nif(process.env.NODE_ENV !== 'production') {\n run()\n} else {\n schedule.scheduleJob('*/5 * * * *', () => { run() })\n}
\nTesting things out:
\nnode index.js
\nHere's a link to the github repo.
","avatar":null},{"id":"cjeqgfri4nnqd0199zsv6a9fl","title":"Hexo - The Best Static Site Generator? ","slug":"deploy-a-hexo-blog","published_at":"2018-04-01T16:00:00","created_at":"2018-03-14T02:16:40","excerpt":" Hexo is The Jam!","image":null,"posts_tags":[],"date":"April 1, 2018","html":"There are dizzying number of static site generators. Excessive choice and paralysis by analysis are now part of the javascript ecosystem.
\n\nI've used the ruby-based generators (Middleman, Jekyll). I've also used content management solutions like Ghost, Wordpress, and the like. So far, Hexo is my absolute favorite static site generator. Here's why:
\nBut the biggest merit of Hexo is that it lacks the demerits of other blogging solutions. Let me explain.
\nGhost is OK. But it can be a pain to configure and deploy. Updating Ghost is not as straightforward as it could be. The CMS seems bloated for simply serving up static files. There are no plugins. What if you want to spin up a new website in 10 minutes? Ghost is not so quick to deploy and customize.
\nMiddleman was fun. It uses yaml, whick is a plus. But the community is relively dead. Configuration is challenging (my personal bias - I'm not a ruby guy).
\nGatsby is a static site generator built around React. React is sexy, no doubt. It fits with one's mental model of what a UI framework should be. But Gatsby seems like a prime example of overengineering at its finest. Why would I want to write JSX, only to have it compiled into html?
\nI'll assume that npm is intalled on your machine, but that's about it.
\nFirst, install the Hexo command line interface globally.
\nnpm install hexo-cli -g
\nNow let's start a new project:
\nhexo init my-project\ncd my-project
\nYour project structure will look something like:
\nGenerate your static site with:
\nhexo generate
\nYour static files will be generated in the folder public.
\nIf you poke around in source/_posts, you'll see that posts are marked files with frontmatter, e.g.:
\n---\ntitle: deploy-a-hexo-blog.md\ndate: 2017-07-10 22:50:35\ntags: \n- javascript\n- hexo\n- Development
\nHexo 3 dissociated the server from the main node module. Therefore you need to install hexo-server:
\nnpm install hexo-server --save
\nStart the server:
\nhexo server
\nAside: you don't need to use the node server in production. Hexo generates static files in ./public that can be served up with nginx, Apache, etc.
\nDeploymnet options with Hexo are unlimited.
\nInstall the heroku deployment plugin:
\nnpm install hexo-deployer-heroku --save
\nAdd these settings to _config.yml
Create a new heroku project:
\ncd my-project\nheroku create\ngit remote -v ## confirm that the heroku remote was added
\nNow that you have a heroku repository url, add it to your _config.yml:
\nYou can use this:
\ndeploy:\n type: heroku \n repo: \n message: [message]
\nFinally, deploy your new Hexo project:
\nhexo generate --deploy # or what amounts to the same thing:\nheroku deploy --generate\nheroku deploy # deploy without generating
\nFollow the initial DigitalOcean setup here
","avatar":null}]}}}