{
    "version": "https://jsonfeed.org/version/1",
    "title": "mrvautin",
    "home_page_url": "https://mrvautin.com",
    "feed_url": "https://mrvautin.com/json",
    "description": "mrvautin",
    "items": [
        {
            "id": "https://mrvautin.com/home-assistant-create-date-countdown-template-sensor/",
            "content_html": "<h1 id=\"home-assistant---create-date-countdown-template-sensor\">Home assistant - Create date countdown template sensor</h1>\n<p>Imagine you have a big event coming up, a holiday or a graduation - Quickly and easily setup a sensor to track the big day.</p>\n<p>Jump into your <code>configuration.yaml</code> file in your <code>config/</code> directory either via the file system or via the VSCode extension in Home assistant.</p>\n<p>You are going to want to add a sensor for each event. Below we've setup two events - A birthday and a Marathon. You simply need to adjust the dates below to your desired date and update the name and ID for your sensor.</p>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;My Birthday&quot;</span>\n        <span class=\"hljs-attr\">friendly_name:</span> <span class=\"hljs-string\">&quot;my_birthday&quot;</span>\n        <span class=\"hljs-attr\">unit_of_measurement:</span> <span class=\"hljs-string\">&quot;days&quot;</span>\n        <span class=\"hljs-attr\">icon:</span> <span class=\"hljs-string\">mdi:calendar</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&gt;\n          {{ (strptime(&#x27;02/03/2025&#x27;, &#x27;%d/%m/%Y&#x27;, today_at()) | as_local - today_at()).days }}\n</span>  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;My Marathon&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;marathon&quot;</span>\n        <span class=\"hljs-attr\">unit_of_measurement:</span> <span class=\"hljs-string\">&quot;days&quot;</span>\n        <span class=\"hljs-attr\">icon:</span> <span class=\"hljs-string\">mdi:calendar</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&gt;\n          {{ (strptime(&#x27;04/08/2025&#x27;, &#x27;%d/%m/%Y&#x27;, today_at()) | as_local - today_at()).days }}\n</span></code></pre>\n<p>After you've updated your <code>configuration.yaml</code> file, save it and restart Home Assistant to see the new sensors named <code>my_birthday</code> and one called <code>marathon</code> or whatever you changed them to.</p>\n<p>You can then head to your dashboard and add a new <code>Entities Card</code>. Pop the names of the entities you created above to display on your dashboard.</p>\n",
            "url": "https://mrvautin.com/home-assistant-create-date-countdown-template-sensor/",
            "title": "Home assistant - Create date countdown template sensor",
            "summary": "Imagine you have a big event coming up, a holiday, a graduation - Quickly and easily setup a sensor to track the big day",
            "date_modified": "2025-01-10T11:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/guide-to-creating-template-sensors-in-home-assistant/",
            "content_html": "<h1 id=\"home-assistant---guide-to-creating-template-sensors-in-home-assistant\">Home Assistant - Guide to Creating Template Sensors in Home Assistant</h1>\n<p>Home Assistant's Template Sensors allow you to create custom sensors using data from existing entities and templates. This guide will walk you through the process of creating Template Sensors using YAML.</p>\n<p>Table of Contents</p>\n<ol>\n<li>Prerequisites</li>\n<li>Understanding Template Sensors</li>\n<li>Creating Template Sensors</li>\n</ol>\n<ul>\n<li>Basic Structure</li>\n<li>Adding to <code>configuration.yaml</code></li>\n</ul>\n<ol start=\"4\">\n<li>Examples of Template Sensors</li>\n</ol>\n<ul>\n<li>Combining Two Sensors</li>\n<li>Calculating a Value</li>\n<li>Formatting Time or Date</li>\n</ul>\n<ol start=\"5\">\n<li>Testing and Validating Configuration</li>\n<li>Restarting Home Assistant</li>\n<li>Advanced Use Cases</li>\n<li>Troubleshooting</li>\n</ol>\n<h2 id=\"prerequisites\">Prerequisites</h2>\n<ol>\n<li>A working installation of Home Assistant.</li>\n<li>Access to the Home Assistant configuration files, particularly <code>configuration.yaml</code>.</li>\n<li>Basic knowledge of YAML and Jinja2 templating syntax.</li>\n</ol>\n<h2 id=\"understanding-template-sensors\">Understanding Template Sensors</h2>\n<p>Template Sensors in Home Assistant are virtual sensors. They are not physical devices but are computed based on templates, often combining data from multiple entities or transforming raw data into a more meaningful format.</p>\n<h2 id=\"creating-template-sensors\">Creating Template Sensors</h2>\n<h3 id=\"basic-structure\">Basic Structure</h3>\n<p>A Template Sensor is defined in the <code>configuration.yaml</code> file under the template: key. Below is the basic structure:</p>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;Template Sensor Name&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;unique_id_for_this_sensor&quot;</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.existing_sensor&#x27;) }}</span>&quot;</span>\n        <span class=\"hljs-attr\">attributes:</span>\n          <span class=\"hljs-attr\">custom_attribute:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.another_sensor&#x27;) }}</span>&quot;</span>\n        <span class=\"hljs-attr\">unit_of_measurement:</span> <span class=\"hljs-string\">&quot;°C&quot;</span>\n        <span class=\"hljs-attr\">state_class:</span> <span class=\"hljs-string\">&quot;measurement&quot;</span>\n</code></pre>\n<h3 id=\"adding-to-configuration.yaml\">Adding to configuration.yaml</h3>\n<ol>\n<li>Open your <code>configuration.yaml</code> file.</li>\n<li>Add the template: key if it doesn’t exist.</li>\n<li>Add your Template Sensor configuration under the template: section.</li>\n</ol>\n<h2 id=\"examples-of-template-sensors\">Examples of Template Sensors</h2>\n<h3 id=\"combining-two-sensors\">Combining Two Sensors</h3>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;Total Power Consumption&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;total_power_consumption&quot;</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.power_meter_1&#x27;) | float + states(&#x27;sensor.power_meter_2&#x27;) | float }}</span>&quot;</span>\n        <span class=\"hljs-attr\">unit_of_measurement:</span> <span class=\"hljs-string\">&quot;W&quot;</span>\n</code></pre>\n<h3 id=\"calculating-a-value\">Calculating a Value</h3>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;Room Temperature in Fahrenheit&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;room_temp_fahrenheit&quot;</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ (states(&#x27;sensor.room_temp_celsius&#x27;) | float * 9/5) + 32 }}</span>&quot;</span>\n        <span class=\"hljs-attr\">unit_of_measurement:</span> <span class=\"hljs-string\">&quot;°F&quot;</span>\n</code></pre>\n<h3 id=\"formatting-time-or-date\">Formatting Time or Date</h3>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;Current Time&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;current_time&quot;</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ now().strftime(&#x27;%H:%M:%S&#x27;) }}</span>&quot;</span>\n</code></pre>\n<h2 id=\"testing-and-validating-configuration\">Testing and Validating Configuration</h2>\n<p>After adding your Template Sensor:</p>\n<ol>\n<li>Run a configuration check in Home Assistant:</li>\n</ol>\n<ul>\n<li>Go to <code>Settings</code> &gt; <code>System</code> &gt; <code>Check Configuration</code>.</li>\n<li>Fix any errors that appear.</li>\n</ul>\n<ol start=\"2\">\n<li>If no errors are found, restart Home Assistant to apply the changes.</li>\n</ol>\n<h2 id=\"restarting-home-assistant\">Restarting Home Assistant</h2>\n<ol>\n<li>Go to <code>Settings</code> &gt; <code>System</code> &gt; <code>Restart</code>.</li>\n<li>Wait for Home Assistant to restart and then check if the new Template Sensor appears under <code>Developer Tools</code> &gt; <code>States</code>.</li>\n</ol>\n<h2 id=\"advanced-use-cases\">Advanced Use Cases</h2>\n<h3 id=\"adding-multiple-attributes\">Adding Multiple Attributes</h3>\n<p>You can add custom attributes to your Template Sensors:</p>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;Weather Overview&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;weather_overview&quot;</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.weather_condition&#x27;) }}</span>&quot;</span>\n        <span class=\"hljs-attr\">attributes:</span>\n          <span class=\"hljs-attr\">temperature:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.outdoor_temp&#x27;) }}</span>&quot;</span>\n          <span class=\"hljs-attr\">humidity:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.outdoor_humidity&#x27;) }}</span>&quot;</span>\n          <span class=\"hljs-attr\">wind_speed:</span> <span class=\"hljs-string\">&quot;<span class=\"hljs-template-variable\">{{ states(&#x27;sensor.wind_speed&#x27;) }}</span>&quot;</span>\n</code></pre>\n<h3 id=\"using-conditions-in-templates\">Using Conditions in Templates</h3>\n<p>Use Jinja2 conditionals to create dynamic sensor values:</p>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">template:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">sensor:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">&quot;Weather Status&quot;</span>\n        <span class=\"hljs-attr\">unique_id:</span> <span class=\"hljs-string\">&quot;weather_status&quot;</span>\n        <span class=\"hljs-attr\">state:</span> <span class=\"hljs-string\">&gt;\n          {% if states(&#x27;sensor.temperature&#x27;) | float &gt; 30 %}\n            Hot\n          {% elif states(&#x27;sensor.temperature&#x27;) | float &gt; 20 %}\n            Warm\n          {% else %}\n            Cold\n          {% endif %}\n</span></code></pre>\n<p>Troubleshooting</p>\n<ul>\n<li>Error in Configuration Check: Verify the indentation and syntax in your <code>configuration.yaml</code>.</li>\n<li>Sensor Not Updating: Check the state or availability of the referenced entities.</li>\n<li>Template Syntax Errors: Test your template in <code>Developer Tools</code> &gt; <code>Templates</code> in the Home Assistant interface.</li>\n<li>Sensor Not Showing in UI: Ensure the <code>unique_id</code> is unique and correctly configured.</li>\n</ul>\n<p>That’s it! You now have the knowledge to create and customize Template Sensors in Home Assistant. Use this feature to expand the functionality of your smart home system!</p>\n",
            "url": "https://mrvautin.com/guide-to-creating-template-sensors-in-home-assistant/",
            "title": "Home Assistant - Guide to Creating Template Sensors in Home Assistant",
            "summary": "A comprehensive guide into creating template sensors in Home Assistant",
            "date_modified": "2025-01-05T11:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/react-native-change-folder-of-app.js-tsx-for-app-to-subfolder/",
            "content_html": "<h1 id=\"react-native---change-folder-of-app.js-or-app.tsx-to-subfolder\">React Native - Change folder of App.js or App.tsx to subfolder</h1>\n<h2 id=\"introduction\">Introduction</h2>\n<p>You may want to next your app within a different folder to make your dev environment cleaner. You can do this by moving your <code>App.js</code> or <code>App.tsx</code> into a <code>/app</code> folder.</p>\n<h2 id=\"setup\">Setup</h2>\n<p>I'm going to move my app into a <code>/app</code> folder but you may use <code>/src</code> etc.</p>\n<p>Say my structure is currently like this:</p>\n<pre><code>.expo/\nApp.tsx\nios/\nnode_modules/\n.gitignore\napp.json\npackage.json\n...\n</code></pre>\n<p>First we will create our <code>/app</code> folder.</p>\n<p>We can then move our <code>App.tsx</code> (<code>App.js</code>) and the rest of my app <code>/assets</code> etc to this folder.</p>\n<p>Within that folder we will create an <code>AppEntry.tsx</code> file:</p>\n<pre><code class=\"language-typescript\"><span class=\"hljs-keyword\">import</span> registerRootComponent <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;expo/build/launch/registerRootComponent&#x27;</span>;\n\n<span class=\"hljs-keyword\">import</span> App <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;./App&#x27;</span>;\n\nregisterRootComponent(App);\n</code></pre>\n<p>Lastly, we need to tell the app where the entrypoint is. We will need to update our <code>package.json</code> file by setting the <code>main</code>:</p>\n<pre><code class=\"language-json\">{\n  &quot;name&quot;: &quot;my-app&quot;,\n  &quot;version&quot;: &quot;1.0.0&quot;,\n  &quot;main&quot;: &quot;app/AppEntry.tsx&quot;,\n  &quot;scripts&quot;: {\n    &quot;start&quot;: &quot;expo start&quot;,\n    &quot;android&quot;: &quot;expo run:android&quot;,\n    &quot;ios&quot;: &quot;expo run:ios&quot;,\n    &quot;web&quot;: &quot;expo start --web&quot;\n  },\n  ...\n}\n</code></pre>\n<p>You will end up with a structure like:</p>\n<pre><code>.expo/\napp/App.tsx\napp/AppEntry.tsx\napp/assets/logo.png\nios/\nnode_modules/\n.gitignore\napp.json\npackage.json\n...\n</code></pre>\n<p>That's it, start your app with <code>npm run ios</code> and away you go. Good luck!</p>\n",
            "url": "https://mrvautin.com/react-native-change-folder-of-app.js-tsx-for-app-to-subfolder/",
            "title": "React Native - Change folder of App.js or App.tsx into subfolder",
            "summary": "You may want to next your app within a different sub folder to make your dev environment cleaner. You can do this by moving your App.js or App.tsx into a /app folder.",
            "date_modified": "2024-02-26T11:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/setting-up-home-assistant-on-apple-carplay-a-step-by-step-guide/",
            "content_html": "<h1 id=\"setting-up-home-assistant-on-apple-carplay%3A-a-step-by-step-guide\">Setting Up Home Assistant on Apple CarPlay: A Step-by-Step Guide</h1>\n<h2 id=\"introduction\">Introduction</h2>\n<p><a href=\"https://www.home-assistant.io/\">Home Assistant</a> is a powerful open-source platform for smart home automation, and with the increasing integration of technology into our daily lives, having access to your home automation system while on the go can be incredibly convenient. If you're an Apple CarPlay user, you can now extend the reach of Home Assistant to your car, allowing you to control various smart devices on the move. In this guide, we'll walk you through the process of setting up Home Assistant on Apple CarPlay.</p>\n<h2 id=\"prerequisites\">Prerequisites</h2>\n<p>Before you begin, ensure you have the following:</p>\n<ol>\n<li>An Apple CarPlay-compatible vehicle or head unit.</li>\n<li>An iPhone running iOS 12 or later.</li>\n<li>Home Assistant instance set up and accessible from the internet.</li>\n</ol>\n<h2 id=\"step-1%3A-install-the-home-assistant-companion-app\">Step 1: Install the Home Assistant Companion App</h2>\n<ol>\n<li>Open the App Store on your iPhone.</li>\n<li>Search for &quot;Home Assistant&quot; and download the official <a href=\"https://apps.apple.com/us/app/home-assistant/id1099568401\">Home Assistant Companion App</a>.</li>\n<li>Open the app and log in with your Home Assistant credentials.</li>\n</ol>\n<h2 id=\"step-2%3A-enable-carplay-integration\">Step 2: Enable CarPlay Integration</h2>\n<ol>\n<li>In the Home Assistant app, navigate to &quot;App Configuration&quot; from the sidebar.</li>\n<li>Tap on &quot;CarPlay&quot; to access CarPlay settings.</li>\n<li>Toggle the switch to enable CarPlay integration.</li>\n</ol>\n<h2 id=\"step-3%3A-configure-carplay-dashboard\">Step 3: Configure CarPlay Dashboard</h2>\n<ol>\n<li>Connect your iPhone to your CarPlay-compatible vehicle or head unit.</li>\n<li>Open the CarPlay interface, and you should see the Home Assistant icon.</li>\n<li>Tap the Home Assistant icon to launch the CarPlay dashboard.</li>\n</ol>\n<h2 id=\"step-4%3A-customize-carplay-dashboard\">Step 4: Customize CarPlay Dashboard</h2>\n<ol>\n<li>Once in the CarPlay dashboard, you can customize the interface by adding or removing cards.</li>\n<li>Press and hold on a card to enter edit mode.</li>\n<li>Use the on-screen options to add cards, rearrange them, or remove unwanted ones.</li>\n</ol>\n<h2 id=\"step-5%3A-control-your-smart-home-on-the-go\">Step 5: Control Your Smart Home On the Go</h2>\n<ol>\n<li>With Home Assistant on CarPlay, you can now control your smart devices from the dashboard.</li>\n<li>Use voice commands via Siri to perform actions like turning off lights, adjusting thermostat settings, or locking doors.</li>\n</ol>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>Setting up Home Assistant on Apple CarPlay brings your smart home control to the driver's seat, providing a seamless and convenient way to manage your devices while on the move. With the integration of CarPlay, Home Assistant continues to demonstrate its commitment to making home automation accessible wherever you are. Try out this guide, and enjoy the convenience of controlling your smart home right from your car. Safe driving!</p>\n",
            "url": "https://mrvautin.com/setting-up-home-assistant-on-apple-carplay-a-step-by-step-guide/",
            "title": "Setting Up Home Assistant on Apple CarPlay - A Step-by-Step Guide",
            "summary": "If you're an Apple CarPlay user, you can now extend the reach of Home Assistant to your car, allowing you to control various smart devices on the move. In this guide, we'll walk you through the process of setting up Home Assistant on Apple CarPlay.",
            "date_modified": "2024-01-31T11:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/why-to-use-nodejs-top-6-advantages-of-using-nodejs/",
            "content_html": "<p>Node.js is a popular open-source, cross-platform runtime environment that is designed to run JavaScript on the server-side. It is built on top of the Google V8 JavaScript engine and provides developers with a powerful platform for building scalable and high-performance applications. In this blog post, we will explore why you should use Node.js and its advantages.</p>\n<h2 id=\"1.-javascript-everywhere\">1. JavaScript Everywhere</h2>\n<p>One of the primary advantages of Node.js is that it allows developers to use the same programming language, i.e., JavaScript, on both the server-side and client-side. This means that developers can use the same programming language for both front-end and back-end development, which reduces the learning curve and makes it easier to switch between different development tasks.</p>\n<h2 id=\"2.-high-performance\">2. High Performance</h2>\n<p>Node.js is known for its high performance and scalability. It is designed to handle a large number of simultaneous connections and requests, making it ideal for building real-time applications such as chat applications, online games, and collaborative tools. Additionally, Node.js uses an event-driven, non-blocking I/O model, which makes it highly efficient and able to handle large amounts of data without slowing down or crashing.</p>\n<h2 id=\"3.-large-community\">3. Large Community</h2>\n<p>Node.js has a large and active community of developers, which means that there is a wealth of resources available for developers to learn from and leverage. The Node.js community has created a vast ecosystem of modules, packages, and tools that make it easier to build and maintain Node.js applications.</p>\n<h2 id=\"4.-easy-to-learn\">4. Easy to Learn</h2>\n<p>As mentioned earlier, Node.js uses JavaScript, which is one of the most popular programming languages in the world. This means that developers who are already familiar with JavaScript can easily learn Node.js and start building applications. Additionally, Node.js has a simple and intuitive API, making it easy for developers to get started quickly.</p>\n<h2 id=\"5.-cross-platform\">5. Cross-Platform</h2>\n<p>Node.js is a cross-platform runtime environment, which means that developers can use it on Windows, macOS, Linux, and other operating systems. This makes it easier to build and deploy applications across different platforms without having to make significant changes to the code.</p>\n<h2 id=\"6.-scalability\">6. Scalability</h2>\n<p>Node.js is designed to handle large-scale applications and can easily scale to meet the needs of growing businesses. It uses a modular approach to building applications, which means that developers can add new functionality and features as needed without having to rewrite the entire application.</p>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>In conclusion, Node.js is an excellent choice for building high-performance, scalable, and real-time applications. Its ease of use, cross-platform compatibility, and vast ecosystem of modules and tools make it an ideal platform for developers to build applications quickly and efficiently. So, if you are looking for a powerful and flexible platform for your next project, consider using Node.js.1.</p>\n",
            "url": "https://mrvautin.com/why-to-use-nodejs-top-6-advantages-of-using-nodejs/",
            "title": "Why to use Nodejs - Top 6 advantages of using NodeJs",
            "summary": "Why to use Nodejs - Top 6 advantages of using NodeJs",
            "date_modified": "2023-03-05T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/a-comprehensive-guide-install-home-assistant-on-your-computer/",
            "content_html": "<p>Home Assistant is an open-source platform that allows you to control various smart devices in your home from a single location. It is a popular home automation system that is easy to install and use. In this guide, we will walk you through the steps of installing Home Assistant on your computer.</p>\n<h1 id=\"prerequisites\">Prerequisites</h1>\n<p>Before you begin, you will need the following:</p>\n<ul>\n<li>A computer running Windows, macOS, or Linux</li>\n<li>Python 3.8 or higher installed on your computer</li>\n<li>A virtual environment set up on your computer (optional but recommended)</li>\n</ul>\n<h1 id=\"step-1%3A-install-home-assistant\">Step 1: Install Home Assistant</h1>\n<p>To install Home Assistant, follow these steps:</p>\n<ol>\n<li>Open a terminal or command prompt on your computer.</li>\n<li>Activate your virtual environment (if you have set one up).</li>\n<li>Enter the following command to install Home Assistant:</li>\n</ol>\n<pre><code class=\"language-bash\">pip install homeassistant\n</code></pre>\n<ol start=\"4\">\n<li>Wait for the installation to complete.</li>\n</ol>\n<h1 id=\"step-2%3A-set-up-home-assistant\">Step 2: Set Up Home Assistant</h1>\n<p>Once Home Assistant is installed, you need to set it up. Here are the steps:</p>\n<ol>\n<li>Enter the following command to start Home Assistant:</li>\n</ol>\n<pre><code class=\"language-bash\">hass\n</code></pre>\n<ol start=\"2\">\n<li>Wait for Home Assistant to start up. This may take a few minutes the first time you run it.</li>\n<li>Open a web browser and go to <code>http://localhost:8123</code>.</li>\n<li>Follow the instructions to set up Home Assistant.</li>\n</ol>\n<h1 id=\"step-3%3A-add-devices-and-integrations\">Step 3: Add Devices and Integrations</h1>\n<p>Once you have set up Home Assistant, you can start adding devices and integrations. Here's how:</p>\n<ol>\n<li>Click on <code>Configuration</code> in the Home Assistant sidebar.</li>\n<li>Click on <code>Integrations</code> and then click the <code>+</code> button.</li>\n<li>Select the integration you want to add and follow the instructions.</li>\n<li>Once you have added an integration, you can start using it in Home Assistant.</li>\n</ol>\n<h1 id=\"conclusion\">Conclusion</h1>\n<p>Congratulations! You have successfully installed and set up Home Assistant on your computer.</p>\n<p>Now you can start adding devices and integrations to control your smart home from a single location. If you encounter any issues during the installation process, refer to the Home Assistant documentation or seek help from the Home Assistant community.</p>\n",
            "url": "https://mrvautin.com/a-comprehensive-guide-install-home-assistant-on-your-computer/",
            "title": "Home Assistant - A Comprehensive Guide to install Home Assistant on Your Computer",
            "summary": "Home Assistant - A Comprehensive Guide to install Home Assistant on Your Computer",
            "date_modified": "2023-03-04T01:01:00.000Z"
        },
        {
            "id": "https://mrvautin.com/home-assistant-a-comprehensive-guide-to-your-smart-home/",
            "content_html": "<p>With the increasing popularity of smart home technology, managing all of your devices and automating your daily routines can be a daunting task. However, with Home Assistant, you can easily control all of your smart home devices and customize your home automation to fit your unique needs.</p>\n<h1 id=\"what-is-home-assistant%3F\">What is Home Assistant?</h1>\n<p>Home Assistant is an open-source home automation platform that allows you to control all of your smart home devices from a central location. With Home Assistant, you can integrate all of your smart devices into a single platform, create customized automations, and monitor your home's status and activity.</p>\n<p>Home Assistant supports a wide range of smart home devices, including lights, thermostats, sensors, cameras, and more. It also supports popular smart home protocols like Zigbee, Z-Wave, Wi-Fi, and Bluetooth.</p>\n<h1 id=\"getting-started-with-home-assistant\">Getting Started with Home Assistant</h1>\n<p>Getting started with Home Assistant is easy, but it does require some technical know-how. To get started, you will need to download and install the Home Assistant software on a device like a Raspberry Pi or a dedicated server.</p>\n<p>Once you have installed Home Assistant, you can start adding your smart devices to the platform. Home Assistant supports a wide range of devices and protocols, but you will need to ensure that your devices are compatible with the platform before you start adding them.</p>\n<h1 id=\"customizing-your-smart-home-automation\">Customizing Your Smart Home Automation</h1>\n<p>One of the great benefits of Home Assistant is the ability to customize your smart home automation. With Home Assistant, you can create complex automations that trigger based on a variety of conditions and events.</p>\n<p>For example, you can create an automation that turns on your living room lights when you enter the room and turns them off when you leave. You can also create automations that adjust your thermostat based on the time of day or the weather outside.</p>\n<p>In addition to creating automations, Home Assistant also supports custom scripts that can be triggered by voice commands or other events. This allows you to create custom actions that are not supported by your smart home devices out of the box.</p>\n<h1 id=\"monitoring-your-smart-home\">Monitoring Your Smart Home</h1>\n<p>Home Assistant also provides a dashboard that allows you to monitor your smart home devices and activity. The dashboard provides real-time information about your home's status, including the temperature, humidity, and energy usage.</p>\n<p>You can also set up alerts and notifications that notify you when certain conditions are met. For example, you can set up an alert that notifies you when the front door is opened or when a motion sensor is triggered.</p>\n<h1 id=\"conclusion\">Conclusion</h1>\n<p>Home Assistant is a powerful home automation platform that provides a comprehensive solution for managing your smart home devices. With Home Assistant, you can integrate all of your devices into a single platform, create custom automations, and monitor your home's status and activity.</p>\n<p>If you're looking to take your smart home to the next level, Home Assistant is definitely worth checking out. While it does require some technical know-how to get started, the customization and control it provides over your smart home devices is unparalleled.</p>\n",
            "url": "https://mrvautin.com/home-assistant-a-comprehensive-guide-to-your-smart-home/",
            "title": "Home Assistant - A Comprehensive Guide to Your Smart Home",
            "summary": "Home Assistant - A Comprehensive Guide to Your Smart Home",
            "date_modified": "2023-03-04T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/helpkb-open-source-and-easy-to-use-knowledge-base-faq/",
            "content_html": "<img src=\"/content/images/helpkb/helpkb.png\" width=\"200px\" height=\"200px\" class=\"img-fluid\">\n<p><a href=\"https://helpkb.org\">helpkb</a> is a superfast and easy to use knowledge base / FAQ to help your customers get the info they need, when they need it most.</p>\n<p>It's been proven that empowering your customers and staff to self serve and access information quickly and easily will boost customer satisfaction, reduce queries and make everyone's life easier. We've created <a href=\"https://helpkb.org\">helpkb</a> to do just that. A FREE, super fast and easy to use knowledge base or FAQ so information is always on hand.</p>\n<p>So checkout the <a href=\"https://docs.helpkb.org\">documentation / demo</a>, and follow our <a href=\"https://helpkb.org/getting-started/\">guide</a> to get started building your knowledge base / FAQ today!</p>\n<h4 id=\"screenshot%3A\">Screenshot:</h4>\n<p><img src=\"/content/images/helpkb/helpkb-screenshot.jpg\" alt=\"helpkb screenshot\"></p>\n",
            "url": "https://mrvautin.com/helpkb-open-source-and-easy-to-use-knowledge-base-faq/",
            "title": "helpkb - An open-source and easy to use knowledge base / FAQ",
            "summary": "helpkb - An open-source and easy to use knowledge base / FAQ",
            "date_modified": "2022-07-03T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/taxily-an-australian-income-tax-net-pay-superannuation-savings-calculator/",
            "content_html": "<p><a href=\"https://taxily.markmoffat.com\">taxily</a> allows you to calculate your Australian annual Income, Net pay, Superannuation and Savings with a few simple inputs using the official ATO tax rates.</p>\n<p><img src=\"/content/images/taxily-inputs.jpg\" alt=\"taxily inputs\"></p>\n<p>Once you've entered your income and your income cycle you will get a beautiful report showing all the calculated values:</p>\n<p><img src=\"/content/images/taxily-output.jpg\" alt=\"taxily inputs\"></p>\n<h3 id=\"access-taxily.markmoffat.com\">Access <a href=\"https://taxily.markmoffat.com\">taxily.markmoffat.com</a></h3>\n",
            "url": "https://mrvautin.com/taxily-an-australian-income-tax-net-pay-superannuation-savings-calculator/",
            "title": "taxily - An Australian Income Tax, Net Pay, Superannuation and Savings calculator",
            "summary": "taxily - An Australian Income Tax, Net Pay, Superannuation and Savings calculator",
            "date_modified": "2022-03-29T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/deploying-your-nextjs-website-without-any-downtime/",
            "content_html": "<p>In an ideal world, you'd build your <a href=\"https://nextjs.org/\">Next.js</a> app locally, check it works then deploy the built app to your production server.</p>\n<p>Sometimes you just want to deploy your <a href=\"https://nextjs.org/\">Next.js</a> website on the server and not build locally as stated above. To do this we are going to setup a simple shell script and use <a href=\"https://pm2.keymetrics.io/docs/usage/deployment/\">PM2</a> to deploy with no downtime.</p>\n<p>An example <a href=\"https://pm2.keymetrics.io/docs/usage/deployment/\">PM2</a> <code>ecosystem.config.js</code> file in the root of your project:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-built_in\">module</span>.exports = {\n   <span class=\"hljs-attr\">apps</span>: [\n      {\n         <span class=\"hljs-attr\">name</span>: <span class=\"hljs-string\">&#x27;my-app&#x27;</span>,\n         <span class=\"hljs-attr\">script</span>: <span class=\"hljs-string\">&#x27;npm run start&#x27;</span>,\n         <span class=\"hljs-attr\">cwd</span>: <span class=\"hljs-string\">&#x27;/Users/mrvautin/Documents/Code/my-app/&#x27;</span>,\n         <span class=\"hljs-attr\">env</span>: {\n               <span class=\"hljs-attr\">NODE_ENV</span>: <span class=\"hljs-string\">&#x27;development&#x27;</span>\n         },\n         <span class=\"hljs-attr\">env_production</span>: {\n               <span class=\"hljs-attr\">NODE_ENV</span>: <span class=\"hljs-string\">&#x27;production&#x27;</span>\n         }\n      }\n   ],\n   <span class=\"hljs-attr\">deploy</span>: {\n      <span class=\"hljs-attr\">production</span>: {\n         <span class=\"hljs-attr\">user</span>: <span class=\"hljs-string\">&#x27;my-user&#x27;</span>,\n         <span class=\"hljs-attr\">host</span>: <span class=\"hljs-string\">&#x27;my-server&#x27;</span>,\n         <span class=\"hljs-attr\">key</span>: <span class=\"hljs-string\">&#x27;/Users/mrvautin/.ssh/id_rsa&#x27;</span>,\n         <span class=\"hljs-attr\">ssh_options</span>: <span class=\"hljs-string\">&#x27;ForwardAgent=yes&#x27;</span>,\n         <span class=\"hljs-attr\">ref</span>: <span class=\"hljs-string\">&#x27;origin/main&#x27;</span>,\n         <span class=\"hljs-attr\">repo</span>: <span class=\"hljs-string\">&#x27;[email protected]:mrvautin/my-app.git&#x27;</span>,\n         <span class=\"hljs-attr\">path</span>: <span class=\"hljs-string\">&#x27;/var/www/html/my-app&#x27;</span>,\n         <span class=\"hljs-string\">&#x27;post-deploy&#x27;</span>: <span class=\"hljs-string\">&#x27;sh nextjs-pm2-deploy.sh&#x27;</span>\n      }\n   }\n};\n</code></pre>\n<p>An example <code>package.json</code> with our <code>deploy</code> script:</p>\n<pre><code class=\"language-json\">{\n  <span class=\"hljs-attr\">&quot;name&quot;</span>: <span class=\"hljs-string\">&quot;my-app&quot;</span>,\n  <span class=\"hljs-attr\">&quot;version&quot;</span>: <span class=\"hljs-string\">&quot;0.1.0&quot;</span>,\n  <span class=\"hljs-attr\">&quot;private&quot;</span>: <span class=\"hljs-literal\">true</span>,\n  <span class=\"hljs-attr\">&quot;scripts&quot;</span>: {\n    <span class=\"hljs-attr\">&quot;deploy&quot;</span>: <span class=\"hljs-string\">&quot;pm2 deploy production&quot;</span>\n  },\n  <span class=\"hljs-attr\">&quot;dependencies&quot;</span>: {},\n  <span class=\"hljs-attr\">&quot;devDependencies&quot;</span>: {}\n}\n</code></pre>\n<p>Now the contents of the <code>nextjs-pm2-deploy.sh</code> shell script referenced in the <code>post-deploy</code> section of the <code>ecosystem.config.js</code> file above:</p>\n<pre><code class=\"language-bash\"><span class=\"hljs-built_in\">echo</span> <span class=\"hljs-string\">&quot;Deploy starting...&quot;</span>\n\nnpm run install || <span class=\"hljs-built_in\">exit</span>\n\nBUILD_DIR=temp npm run build || <span class=\"hljs-built_in\">exit</span>\n\n<span class=\"hljs-keyword\">if</span> [ ! -d <span class=\"hljs-string\">&quot;temp&quot;</span> ]; <span class=\"hljs-keyword\">then</span>\n  <span class=\"hljs-built_in\">echo</span> <span class=\"hljs-string\">&#x27;\\033[31m temp Directory not exists!\\033[0m&#x27;</span>  \n  <span class=\"hljs-built_in\">exit</span> 1;\n<span class=\"hljs-keyword\">fi</span>\n\nrm -rf .next\n\nmv temp .next\n\npm2 reload all --update-env\npm2 reset all\n\n<span class=\"hljs-built_in\">echo</span> <span class=\"hljs-string\">&quot;Deploy done.&quot;</span>\n</code></pre>\n<h4 id=\"summary\">Summary</h4>\n<p>Basically, this script will install our app, set the build path to <code>/temp</code>, build the app into <code>/temp</code>, check the <code>/temp</code> directory exists then move the contents over and reset our PM2 instance.</p>\n<p>All this happens in an instant and should see your app deployed with no noticeable downtime.</p>\n",
            "url": "https://mrvautin.com/deploying-your-nextjs-website-without-any-downtime/",
            "title": "Deploying your Next.js website without any downtime",
            "summary": "Of course you can build your Next.js website locally then deploy to the server but sometimes you want to build on the server without any downtime.",
            "date_modified": "2022-03-15T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/setup-wifi-and-ssh-on-raspberry-pi-without-a-monitor/",
            "content_html": "<p>Setting up Wifi and SSH on a Raspberry Pi can be a bit of a pain in the ass. Luckily <code>Raspberry Pi Imager</code> has made things simple with a new config panel to setup before writing the image.</p>\n<ol>\n<li>Download <code>Raspberry Pi Imager</code> <a href=\"https://www.raspberrypi.com/software/\">here</a></li>\n<li>Install <code>Raspberry Pi Imager</code> on your OS</li>\n<li>Open <code>Raspberry Pi Imager</code></li>\n</ol>\n<p><img src=\"/content/images/2022/raspberry-pi-imager-main.jpg\" alt=\"Raspberry Pi Imager\"></p>\n<ol start=\"4\">\n<li><strong>Windows</strong> - Press: <code>CTRL</code>+<code>SHIFT</code>+<code>X</code>\n<br/>\n<strong>MacOS</strong> - Press: <code>CMD</code>+<code>SHIFT</code>+<code>X</code> or <code>CTRL</code>+<code>SHIFT</code>+<code>X</code></li>\n<li>You will be presented with a config to enter your Wifi details, SSH, Locale, Hostname, Keyboard layout and more.</li>\n</ol>\n<p><img src=\"/content/images/2022/raspberry-pi-imager-settings.jpg\" alt=\"Raspberry Pi Imager\"></p>\n",
            "url": "https://mrvautin.com/setup-wifi-and-ssh-on-raspberry-pi-without-a-monitor/",
            "title": "Setup Wifi and SSH on Raspberry Pi without a monitor",
            "summary": "Setting up Wifi and SSH on a Raspberry Pi can be a bit of a pain in the ass. Luckily Raspberry Pi Imager has made things simple with.",
            "date_modified": "2022-01-30T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/squido-a-dead-simple-no-code-static-html-website-builder/",
            "content_html": "<img src=\"https://raw.githubusercontent.com/mrvautin/squido/main/docs/images/squido.svg\" width=\"200px\" height=\"200px\" class=\"img-fluid\">\n<p><a href=\"https://squido.markmoffat.com\">squido</a> is a dead simple static website builder which can be hosted anywhere for super fast static HTML websites and very little effort.</p>\n<p>The advantage of <a href=\"https://squido.markmoffat.com\">squido</a> is that is has all the basics to build and deploy a static website built into the core. This means you don't have to waste time learning the ins and outs, writing code and play around with deployment. You simply do the writing and customization of style / layout and hit deploy.</p>\n<p>Static websites have many benefits seen <a href=\"https://mrvautin.com/advantages-and-disadvantages-of-a-static-html-website-vs-a-complex-dynamic-website\">here</a> but sometimes it's best to simply try for <a href=\"https://squido-docs.markmoffat.com/getting-started/\">yourself</a>.</p>\n<p>So checkout the <a href=\"https://squido-docs.markmoffat.com\">documentation</a>, clone one of the <a href=\"https://squido.markmoffat.com/demo-websites/\">demo repos</a> and get started building your website today!</p>\n<p><img src=\"https://squido.markmoffat.com/content/images/screenshot.png\" alt=\"squido screenshot\"></p>\n",
            "url": "https://mrvautin.com/squido-a-dead-simple-no-code-static-html-website-builder/",
            "title": "squido - A dead simple no-code static HTML website builder",
            "summary": "squido - A dead simple no-code static HTML website builder",
            "date_modified": "2021-04-13T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/advantages-and-disadvantages-of-a-static-html-website-vs-a-complex-dynamic-website/",
            "content_html": "<h2 id=\"what-is-a-static-website%3F\">What is a static website?</h2>\n<p>A static website is comprised entirely of HTML, CSS and Javascript code. In the past static websites were coded by hand but now there are a few builder tools which can compile and build a static website for you.</p>\n<h2 id=\"advantages\">Advantages</h2>\n<ol>\n<li>\n<p><strong>Speed</strong>: Static website generally render much faster than a dynamic website due to not having complex rendering, database queries etc.</p>\n</li>\n<li>\n<p><strong>Cheap</strong>: Static websites can be developed and designed by almost anyone meaning there is reduced costs employing a developer to setup and maintain your website.</p>\n</li>\n<li>\n<p><strong>Simplicity</strong>: Code is easy to read, easy to write and and easier to maintain. Templates/themes are normally provided and can easily be altered to suite your website needs.</p>\n</li>\n<li>\n<p><strong>Hosting</strong>: There are more hosting options available for a static website, many of which are even free - eg: <a href=\"https://pages.github.com/\">Github pages</a> or <a href=\"https://www.netlify.com/\">Netlify</a> which grab your code, build it and host it right from your Git repository. Server hosting needs less resources too due to only serving static content and not needing a Database and server processing.</p>\n</li>\n</ol>\n<h2 id=\"disadvantages\">Disadvantages</h2>\n<ol>\n<li>\n<p><strong>Simplicity</strong>: Simplicity comes at a cost. Static websites lose the ability to do complex processing, database queries etc.</p>\n</li>\n<li>\n<p><strong>Limitations</strong>: There are certain things you simply cannot do making static websites suited to certain website types.</p>\n</li>\n</ol>\n<h2 id=\"when-are-static-websites-a-good-choice%3F\">When are static websites a good choice?</h2>\n<p>Whilst static websites are not suited for all situations, there are some really good instances where a static website is a good alternative to a complex dynamic one. Such as:</p>\n<ul>\n<li>Blogs</li>\n<li>Business websites</li>\n<li>Community information</li>\n<li>Documentation</li>\n<li>Personal website</li>\n<li>Resume</li>\n<li>Portfolio</li>\n<li>Photographer website</li>\n</ul>\n<h2 id=\"getting-started\">Getting started</h2>\n<p>The easiest way to get started is to grab yourself a builder like <a href=\"https://squido.markmoffat.com\">squido</a>. There is some boiler plate / template examples for a <a href=\"https://github.com/mrvautin/squido-blog\">blog</a> or a <a href=\"https://github.com/mrvautin/squido-docs\">documentation</a> website to get you started.</p>\n<p>You can simply clone these repositories, edit the template files, add your colors to the CSS and add your content. You can then follow the steps to <a href=\"https://squido-docs.markmoffat.com/deployment-and-hosting/\">deploy</a> to a hosting provider.</p>\n",
            "url": "https://mrvautin.com/advantages-and-disadvantages-of-a-static-html-website-vs-a-complex-dynamic-website/",
            "title": "Advantages and disadvantages of a static html website vs a complex dynamic website",
            "summary": "Advantages and disadvantages of a static html website vs a complex dynamic website",
            "date_modified": "2021-04-12T01:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/a-dead-simple-module-for-storing-and-managing-your-environment-variables-in-a-simple-and-easy-to-read-yaml-file/",
            "content_html": "<p>Managing your environment variable in your different environments can be a pain. The idea behind <code>envz</code> is that this process is made super simple and easy to understand leading to less mistakes.</p>\n<pre><code class=\"language-bash\"><span class=\"hljs-comment\"># with npm</span>\nnpm install envz\n\n<span class=\"hljs-comment\"># or with Yarn</span>\nyarn add envz\n</code></pre>\n<p>Repo: <a href=\"https://github.com/mrvautin/envz\">https://github.com/mrvautin/envz</a></p>\n<h2 id=\"usage\">Usage</h2>\n<p>You should use <code>envz</code> as early on in the entry point of your app as possible. Eg: <code>app.js</code> or <code>index.js</code> file which loads your app.</p>\n<p>Rather than override <code>process.env.x</code> object, <code>envz</code> will return a new object to use throughout your app.</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">const</span> { envz } = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;envz&#x27;</span>);\n</code></pre>\n<p>Create a <code>env.yaml</code> or any other named file and load it:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">const</span> env = envz(<span class=\"hljs-string\">&#x27;env.yaml&#x27;</span>);\n</code></pre>\n<h2 id=\"env-yaml-file-structure\">env YAML file structure</h2>\n<p>The idea is that the <code>process.env</code> will be merged with loaded <code>yaml</code> file.</p>\n<p><code>env</code> uses a cascading (sequential order) configuration method which is easier to understand looking at an example.</p>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">base:</span>\n  <span class=\"hljs-attr\">PORT:</span> <span class=\"hljs-number\">1234</span>\n  <span class=\"hljs-attr\">config:</span>\n    <span class=\"hljs-attr\">default:</span> <span class=\"hljs-string\">test</span>\n\n<span class=\"hljs-attr\">development:</span>\n  <span class=\"hljs-attr\">PORT:</span> <span class=\"hljs-number\">3000</span>\n  <span class=\"hljs-attr\">DATABASE:</span> <span class=\"hljs-string\">dev</span>\n  <span class=\"hljs-attr\">config:</span>\n    <span class=\"hljs-attr\">token:</span> <span class=\"hljs-number\">12345</span>\n    <span class=\"hljs-attr\">secret:</span> <span class=\"hljs-string\">fwdsdgl</span>\n\n<span class=\"hljs-attr\">production:</span>\n  <span class=\"hljs-attr\">PORT:</span> <span class=\"hljs-number\">80</span>\n  <span class=\"hljs-attr\">DATABASE:</span> <span class=\"hljs-string\">prod</span>\n  <span class=\"hljs-attr\">config:</span>\n    <span class=\"hljs-attr\">token:</span> <span class=\"hljs-number\">67890</span>\n    <span class=\"hljs-attr\">key:</span> <span class=\"hljs-string\">puwndklf</span>\n    <span class=\"hljs-attr\">truthy:</span> <span class=\"hljs-literal\">true</span>\n    <span class=\"hljs-attr\">allowed:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">card</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">phone</span>\n</code></pre>\n<p>The idea here is that the values in <code>base</code> are loaded, anything in <code>development</code> overrides that and finally <code>production</code> overrides that depending on the <code>NODE_ENV</code> set.</p>\n<p>For example, when a <code>NODE_ENV</code> of <code>development</code> is set the following <code>env</code> object is returned:</p>\n<pre><code>PORT: 3000,\nconfig: { \n    default: 'test', \n    token: 12345, \n    secret: 'fwdsdgl' \n},\nDATABASE: 'dev'\n...\n</code></pre>\n<p>Eg: Where the <code>PORT</code> of 3000 from <code>development</code> overrides the <code>base</code> setting of 1234. If the <code>NODE_ENV</code> is set to <code>production</code>, then the <code>PORT</code> will be set to 80.</p>\n<p>The idea behind <code>base</code> (or whatever you want to call it) is that you don't need to redefine defaults over and over for each environment.</p>\n<h2 id=\"options\">Options</h2>\n<p>You can set the environment manually rather than using <code>NODE_ENV</code> by adding an <code>environment</code> object. Eg:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">const</span> env = envz(<span class=\"hljs-string\">&#x27;env.yaml&#x27;</span>, { <span class=\"hljs-attr\">environment</span>: <span class=\"hljs-string\">&#x27;production&#x27;</span> });\n</code></pre>\n<p>By default the values set in <code>process.env</code> overrides what is set in your yaml file. You can change this so that the yaml file is king by adding the following flag:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">const</span> env = envz(<span class=\"hljs-string\">&#x27;env.yaml&#x27;</span>, { <span class=\"hljs-attr\">yamlFileOverride</span>: <span class=\"hljs-literal\">true</span> });\n</code></pre>\n<h2 id=\"save-%2F-update-config\">Save / Update config</h2>\n<p>Sometimes you may want to store changes back to your <code>envz</code> config. You can easily do this by importing <code>save</code>:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">const</span> { save } = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;envz&#x27;</span>);\n</code></pre>\n<p>The <code>save</code> method takes an object with two values:</p>\n<ul>\n<li><code>envfile</code>: The yaml file you are wanting to update</li>\n<li><code>data</code>: The object you want to update back to the file. See tests and example below.</li>\n</ul>\n<pre><code class=\"language-javascript\"><span class=\"hljs-comment\">// In this case we will be adding to the `base` config but you can easily</span>\n<span class=\"hljs-comment\">// replace `base` with `production` or whatever environment.</span>\n<span class=\"hljs-keyword\">const</span> saveObj = <span class=\"hljs-keyword\">await</span> save({\n    <span class=\"hljs-attr\">envfile</span>: <span class=\"hljs-string\">&#x27;test.yaml&#x27;</span>,\n    <span class=\"hljs-attr\">data</span>: {\n      <span class=\"hljs-attr\">base</span>: {\n        <span class=\"hljs-attr\">config</span>: {\n            <span class=\"hljs-attr\">default</span>: <span class=\"hljs-string\">&#x27;default-key&#x27;</span>\n        }\n      }\n    }\n});\n</code></pre>\n<p>This will result in the <code>test.yaml</code> being updated:</p>\n<pre><code class=\"language-yaml\"><span class=\"hljs-attr\">base:</span>\n  <span class=\"hljs-attr\">PORT:</span> <span class=\"hljs-number\">1234</span>\n  <span class=\"hljs-attr\">config:</span>\n    <span class=\"hljs-attr\">default:</span> <span class=\"hljs-string\">default-key</span>\n<span class=\"hljs-string\">...</span>\n</code></pre>\n",
            "url": "https://mrvautin.com/a-dead-simple-module-for-storing-and-managing-your-environment-variables-in-a-simple-and-easy-to-read-yaml-file/",
            "title": "A dead simple module for storing and managing your environment variables in a simple and easy to read yaml file",
            "summary": "A dead simple module for storing and managing your environment variables in a simple and easy to read yaml file",
            "date_modified": "2021-03-18T10:30:00.000Z"
        },
        {
            "id": "https://mrvautin.com/visual-studio-code-helpful-snippets/",
            "content_html": "<p>If you are using VS Code its a huge shame if you aren't making use of the amazingly helpful snippets feature.</p>\n<p>Setting up snippets is easy as:</p>\n<p><strong>Mac</strong></p>\n<p><code>Code &gt; Preferences &gt; User Snippets &gt; Select a file or create a new one</code></p>\n<p><strong>Windows</strong></p>\n<p><code>File &gt; Preferences &gt; User Snippets &gt; Select a file or create a new one</code></p>\n<p>Once setup, snippets are triggered by pressing:</p>\n<p><code>CTRL+Space</code></p>\n<p><img src=\"/content/images/vscode-snippet-menu.png\" alt=\"Snippet menu\"></p>\n<p>Sometimes its easier to look at an example for the Snippets syntax.</p>\n<p>A simple <code>console.log</code> can be sped up using the following syntax. Once triggered the snippet will create a <code>console.log</code> line and drop your cursor into the middle with single quotes wrapping.</p>\n<pre><code class=\"language-json\">{\n    <span class=\"hljs-attr\">&quot;Console log&quot;</span>: {\n        <span class=\"hljs-attr\">&quot;scope&quot;</span>: <span class=\"hljs-string\">&quot;javascript,typescript&quot;</span>,\n        <span class=\"hljs-attr\">&quot;prefix&quot;</span>: <span class=\"hljs-string\">&quot;log&quot;</span>,\n        <span class=\"hljs-attr\">&quot;body&quot;</span>: [\n            <span class=\"hljs-string\">&quot;console.log(&#x27;$1&#x27;);&quot;</span>\n        ],\n        <span class=\"hljs-attr\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;Log output to console&quot;</span>\n    }\n}\n</code></pre>\n<ul>\n<li><strong>Scope:</strong> The file types this snippet is used for</li>\n<li><strong>Prefix:</strong> The snippet name when the snippet menu is opened</li>\n<li><strong>Body:</strong> The main part of the snippet driving the code</li>\n<li><strong>Description:</strong> The description of the snippet</li>\n</ul>\n<h2 id=\"console-logging\">Console logging</h2>\n<p>Simple console logging of text:</p>\n<pre><code class=\"language-json\">{\n    <span class=\"hljs-attr\">&quot;Console log&quot;</span>: {\n        <span class=\"hljs-attr\">&quot;scope&quot;</span>: <span class=\"hljs-string\">&quot;javascript,typescript&quot;</span>,\n        <span class=\"hljs-attr\">&quot;prefix&quot;</span>: <span class=\"hljs-string\">&quot;log&quot;</span>,\n        <span class=\"hljs-attr\">&quot;body&quot;</span>: [\n            <span class=\"hljs-string\">&quot;console.log(&#x27;$1&#x27;);&quot;</span>\n        ],\n        <span class=\"hljs-attr\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;Log output to console&quot;</span>\n    }\n}\n</code></pre>\n<p>Quick and easy logging of the variable in your clipboard.</p>\n<pre><code class=\"language-javascript\">{\n    <span class=\"hljs-string\">&quot;Console log variable&quot;</span>: {\n\t\t<span class=\"hljs-string\">&quot;scope&quot;</span>: <span class=\"hljs-string\">&quot;javascript,typescript&quot;</span>,\n\t\t<span class=\"hljs-string\">&quot;prefix&quot;</span>: <span class=\"hljs-string\">&quot;log var&quot;</span>,\n\t\t<span class=\"hljs-string\">&quot;body&quot;</span>: [\n\t\t\t<span class=\"hljs-string\">&quot;console.log(&#x27;${CLIPBOARD}&#x27;, ${CLIPBOARD});&quot;</span>\n\t\t],\n\t\t<span class=\"hljs-string\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;Console log variable&quot;</span>\n\t}\n}\n</code></pre>\n<h2 id=\"loops\">Loops</h2>\n<p>Quick for loop</p>\n<pre><code class=\"language-json\">{\n    <span class=\"hljs-attr\">&quot;For Loop&quot;</span>: {\n        <span class=\"hljs-attr\">&quot;prefix&quot;</span>: [<span class=\"hljs-string\">&quot;for&quot;</span>, <span class=\"hljs-string\">&quot;for-const&quot;</span>],\n        <span class=\"hljs-attr\">&quot;body&quot;</span>: [<span class=\"hljs-string\">&quot;for (const ${2:element} of ${1:array}) {&quot;</span>, <span class=\"hljs-string\">&quot;\\t$0&quot;</span>, <span class=\"hljs-string\">&quot;}&quot;</span>],\n        <span class=\"hljs-attr\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;A for loop.&quot;</span>\n    }\n}\n</code></pre>\n<h2 id=\"wrapping-text\">Wrapping text</h2>\n<p>Wrapping code blocks in the markdown code block syntax</p>\n<pre><code class=\"language-json\">{\n    <span class=\"hljs-attr\">&quot;Syntax highlighting&quot;</span>: {\n        <span class=\"hljs-attr\">&quot;scope&quot;</span>: <span class=\"hljs-string\">&quot;markdown&quot;</span>,\n        <span class=\"hljs-attr\">&quot;prefix&quot;</span>: <span class=\"hljs-string\">&quot;highlight&quot;</span>,\n        <span class=\"hljs-attr\">&quot;body&quot;</span>: [\n            <span class=\"hljs-string\">&quot;``` javascript&quot;</span>,\n            <span class=\"hljs-string\">&quot;${TM_SELECTED_TEXT}&quot;</span>,\n            <span class=\"hljs-string\">&quot;```&quot;</span>\n        ],\n        <span class=\"hljs-attr\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;Markdown highlight syntax&quot;</span>\n    }\n}\n</code></pre>\n<blockquote>\n<p>For more information on variables available see the official snippet <a href=\"https://code.visualstudio.com/docs/editor/userdefinedsnippets\">docs</a>.</p>\n</blockquote>\n",
            "url": "https://mrvautin.com/visual-studio-code-helpful-snippets/",
            "title": "Visual Studio Code helpful snippets",
            "summary": "Visual Studio Code helpful snippets",
            "date_modified": "2021-03-11T19:17:00.000Z"
        },
        {
            "id": "https://mrvautin.com/interface-with-arduino-board-using-node-js/",
            "content_html": "<p>There are many cheap and solid Arduino compatible boards on the market which can be interfaced/controlled using Node.Js. Today we are going to focus on the <a href=\"https://www.banggood.com/custlink/DGmR9hq9DQ\">WeMos D1 R2 board</a> which can be purchased <a href=\"https://www.banggood.com/custlink/DGmR9hq9DQ\">here</a>.</p>\n<p><img src=\"/content/images/2021/01/a2958102-5e39-4700-aab8-d56d49e67ab2.png\" alt=\"a2958102-5e39-4700-aab8-d56d49e67ab2\"></p>\n<p>This guide assumes you know your way around Node.Js and have it installed along with NPM.</p>\n<p>Firstly you are going to want to setup your board in the Arduino IDE. We will be flashing some simple Wifi firmware to get it on your Wireless network then we can talk to it using Node.Js.</p>\n<ol>\n<li>\n<p>Select the board in the Arduino IDE:</p>\n<p><code>Tools &gt; Board &gt; ESP8266 Boards &gt; WeMos D1 R2</code></p>\n</li>\n<li>\n<p>Plugin your board using a USB cable</p>\n</li>\n<li>\n<p>Open the Wifi firmware:</p>\n<p><code>File &gt; Examples &gt; Firmata &gt; StandardFirmataWifi</code></p>\n</li>\n<li>\n<p>You are going to need to setup your Wifi SSID and Passphrase in the <code>WifiConfig.h</code> file. You shouldn't need to touch the <code>StandardFirmataWifi.h</code> file at all.</p>\n</li>\n<li>\n<p>Scroll to the section which has the Wifi SSID configuration and enter the name of your Wifi network (SSID):</p>\n<pre><code class=\"language-c++\">    <span class=\"hljs-comment\">// replace this with your wireless network SSID</span>\n    <span class=\"hljs-keyword\">char</span> ssid[] = <span class=\"hljs-string\">&quot;your_network_name&quot;</span>;\n</code></pre>\n</li>\n<li>\n<p>Scroll to the section which has the Security configuration and enter your passphrase or Wifi password:</p>\n<pre><code class=\"language-c++\">    <span class=\"hljs-meta\">#<span class=\"hljs-meta-keyword\">ifdef</span> WIFI_WPA_SECURITY</span>\n    <span class=\"hljs-keyword\">char</span> wpa_passphrase[] = <span class=\"hljs-string\">&quot;your_wpa_passphrase&quot;</span>;\n    <span class=\"hljs-meta\">#<span class=\"hljs-meta-keyword\">endif</span> <span class=\"hljs-comment\">//WIFI_WPA_SECURITY</span></span>\n</code></pre>\n</li>\n<li>\n<p>Thats it. You can now compile and upload the code to your board using the <code>Upload</code> button</p>\n</li>\n<li>\n<p>Once that is complete, your board will reset and hopefully connect to your Wifi network.</p>\n</li>\n<li>\n<p>You can now login to your router to check the Wireless clients and determine the IP address of your board. At this point you might like to reserve an IP address using the MAC address for your board so it doesn't change on restart and kill your Node.Js code.</p>\n</li>\n<li>\n<p>Now we are going to setup our Node.Js code to do some simple requests/commands.</p>\n<p>Install our dependencies<br>\n<code>npm i etherport-client johnny-five --save</code></p>\n</li>\n<li>\n<p>Your <code>package.json</code> should look something like this:</p>\n<pre><code class=\"language-json\">{\n    <span class=\"hljs-attr\">&quot;name&quot;</span>: <span class=\"hljs-string\">&quot;nodejs-test&quot;</span>,\n    <span class=\"hljs-attr\">&quot;version&quot;</span>: <span class=\"hljs-string\">&quot;1.0.0&quot;</span>,\n    <span class=\"hljs-attr\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;&quot;</span>,\n    <span class=\"hljs-attr\">&quot;main&quot;</span>: <span class=\"hljs-string\">&quot;index.js&quot;</span>,\n    <span class=\"hljs-attr\">&quot;author&quot;</span>: <span class=\"hljs-string\">&quot;&quot;</span>,\n    <span class=\"hljs-attr\">&quot;license&quot;</span>: <span class=\"hljs-string\">&quot;ISC&quot;</span>,\n    <span class=\"hljs-attr\">&quot;dependencies&quot;</span>: {\n        <span class=\"hljs-attr\">&quot;etherport-client&quot;</span>: <span class=\"hljs-string\">&quot;^0.1.4&quot;</span>,\n        <span class=\"hljs-attr\">&quot;johnny-five&quot;</span>: <span class=\"hljs-string\">&quot;^2.0.0&quot;</span>\n    }\n}\n</code></pre>\n</li>\n<li>\n<p>Now to our Node.Js code. We are going to make the little blue light flash which sits next to the silver <code>WeMos</code> chip on our board:</p>\n<blockquote>\n<p>You will need to change the IP address to the one you found in step 9.</p>\n</blockquote>\n<pre><code class=\"language-javascript\">\n    <span class=\"hljs-keyword\">const</span> { EtherPortClient } = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;etherport-client&#x27;</span>);\n    <span class=\"hljs-keyword\">const</span> { Board, Led } = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;johnny-five&#x27;</span>);\n    \n    <span class=\"hljs-keyword\">const</span> board = <span class=\"hljs-keyword\">new</span> Board({\n        <span class=\"hljs-attr\">port</span>: <span class=\"hljs-keyword\">new</span> EtherPortClient({\n            <span class=\"hljs-attr\">host</span>: <span class=\"hljs-string\">&#x27;192.168.0.201&#x27;</span>,\n            <span class=\"hljs-attr\">port</span>: <span class=\"hljs-number\">3030</span>\n        }),\n        <span class=\"hljs-attr\">repl</span>: <span class=\"hljs-literal\">false</span>\n    });\n    \n    <span class=\"hljs-keyword\">const</span> LED_PIN = <span class=\"hljs-number\">2</span>;\n    \n    board.on(<span class=\"hljs-string\">&#x27;ready&#x27;</span>, <span class=\"hljs-function\">() =&gt;</span> {\n        <span class=\"hljs-built_in\">console</span>.log(<span class=\"hljs-string\">&#x27;Board ready&#x27;</span>);\n        <span class=\"hljs-keyword\">var</span> led = <span class=\"hljs-keyword\">new</span> Led(LED_PIN);\n        led.blink();\n    });\n</code></pre>\n</li>\n<li>\n<p>Now run your code and check the output in the console and the light action on your board.</p>\n<p>You should see some output like this:</p>\n<pre><code class=\"language-bash\">    1610519728478 SerialPort Connecting to host:port: 192.168.0.201:3030\n    1610519728496 Connected Connecting to host:port: 192.168.0.201:3030\n    Board ready\n</code></pre>\n</li>\n</ol>\n<p>And some light action here:<br>\n<img src=\"/content/images/2021/01/IMG_0809.png\" alt=\"IMG_0809\"></p>\n",
            "url": "https://mrvautin.com/interface-with-arduino-board-using-node-js/",
            "title": "Interface with Arduino board using Node.Js",
            "summary": "Interface with an Arduino board using simple Node.JS code",
            "date_modified": "2021-01-14T03:17:00.000Z"
        },
        {
            "id": "https://mrvautin.com/la-marzocco-vector-art/",
            "content_html": "<p>La Marzocco Linea Mini (SVG)</p>\n<p><img src=\"/content/images/2021/01/linea-black-2.svg\" alt=\"\"></p>\n<p><img src=\"/content/images/2021/01/linea-mini-1.svg\" alt=\"\"></p>\n<p>La Marzocco GS3 (SVG)</p>\n<p><img src=\"/content/images/2021/01/gs3-final.svg\" alt=\"\"></p>\n<p>Logos</p>\n<p><img src=\"/content/images/2021/01/La-Marcocco-Logo.svg\" alt=\"La Marzocco Logo\"></p>\n<p><img src=\"/content/images/2021/01/La-Marzocco-Lion.svg\" alt=\"La Marzocco Lion\"></p>\n<p><img src=\"/content/images/2021/01/La-Marzocco-red-logo.svg\" alt=\"La Marzocco cursive logo\"></p>\n",
            "url": "https://mrvautin.com/la-marzocco-vector-art/",
            "title": "La Marzocco - Machine Vector Art & logos",
            "summary": "La Marzocco - Machine Vector Art & logos",
            "date_modified": "2021-01-08T06:21:44.000Z"
        },
        {
            "id": "https://mrvautin.com/ghost-you-are-recommended-to-have-at-least-150-mb-of-memory-available/",
            "content_html": "<p>Sometimes running Ghost on lower powered server like a <a href=\"https://m.do.co/c/cd185d01653f\">Digital Ocean $5 droplet</a> can cause the Ghost CLI to complain about lack of memory: <code>Message: You are recommended to have at least 150 MB of memory available for smooth operation. It looks like you have ~87 MB available.</code></p>\n<p><img src=\"/content/images/2019/06/image.png\" alt=\"Screenshot\"></p>\n<p>Adding the <code>--no-mem-check</code> quickly bypasses this error and gets you on your way.</p>\n<p>Command: <code>ghost update --no-mem-check</code></p>\n",
            "url": "https://mrvautin.com/ghost-you-are-recommended-to-have-at-least-150-mb-of-memory-available/",
            "title": "Ghost - You are recommended to have at least 150 MB of memory available",
            "summary": "Ghost - You are recommended to have at least 150 MB of memory available",
            "date_modified": "2019-06-10T01:25:32.000Z"
        },
        {
            "id": "https://mrvautin.com/bank-loan-repayment-and-interest-calculator/",
            "content_html": "<p>Ever wanted to calculate the repayments on a loan? Ever wanted to know how much interest you will pay over the term of your loan? You are not alone!</p>\n<p>We have created a very simple and beautiful loan calculator so you can quickly and easily see these figures before taking the big step and applying.</p>\n<p>Enjoy! <a href=\"https://calculator.markmoffat.com\">Loan calculator</a></p>\n",
            "url": "https://mrvautin.com/bank-loan-repayment-and-interest-calculator/",
            "title": "Bank Loan repayment and interest calculator",
            "summary": "Bank Loan repayment and interest calculator",
            "date_modified": "2019-04-05T23:54:42.000Z"
        },
        {
            "id": "https://mrvautin.com/connecting-to-mongodb-atlas-with-robo-3t/",
            "content_html": "<p>Sometimes you may want to do development on your database and connect via a GUI to test results. Connecting to MongoDB Atlas is very easy with Robo 3T / Robomongo, simply follow these steps.</p>\n<ol>\n<li>\n<p>Setup your first DNS in your cluster\n<img src=\"/content/images/2018/10/image.png\" alt=\"\"></p>\n</li>\n<li>\n<p>Fill in Database as &quot;admin&quot;, Username/Password as per the user setup in MongoDB Atlas.</p>\n</li>\n</ol>\n<p><img src=\"/content/images/2018/10/image-1.png\" alt=\"\"></p>\n<ol start=\"3\">\n<li>\n<p>Skip SSH tab</p>\n</li>\n<li>\n<p>Click &quot;Use SSL protocol&quot; then select &quot;Self-signed Certificate&quot; from the dropdown.</p>\n</li>\n</ol>\n<p><img src=\"/content/images/2018/10/image-3.png\" alt=\"\"></p>\n<ol start=\"5\">\n<li>Click &quot;Test&quot; button and then &quot;Save&quot;and you are done!</li>\n</ol>\n",
            "url": "https://mrvautin.com/connecting-to-mongodb-atlas-with-robo-3t/",
            "title": "Connecting to MongoDB Atlas with Robo 3T / Robomongo",
            "summary": "Connecting to MongoDB Atlas with Robo 3T / Robomongo",
            "date_modified": "2018-10-10T13:09:18.000Z"
        },
        {
            "id": "https://mrvautin.com/the-best-free-blog-software/",
            "content_html": "<p>Fortunately there are a lot of options for free software to host your shiny new blog. You have definitely heard about <a href=\"https://wordpress.com/\">Wordpress</a> but is it the best option? Well in my option.. no, it's not.</p>\n<p>Sure <a href=\"https://wordpress.com/\">Wordpress</a> has all the bells and whistles with plugins for just about everything but they generally take your website from a blog to a shopping cart or CMS etc. You need to ask yourself, do I really need this stuff? If the answer is no and you just need a blog then <a href=\"https://ghost.org/\">Ghost</a> is the way to go.</p>\n<p><a href=\"https://ghost.org/\">Ghost</a> allows you to quickly and easily setup a beautiful and powerful blog within minutes. There is a cloud hosted option (cost) or a free host your own option.</p>\n<p>Best of all, <a href=\"https://ghost.org/\">Ghost</a> is powerful but not vulnerable and requiring updates every 10 minutes for the 50 Wordpress plugins you have installed.</p>\n<p>So next time you are looking for some blogging software, give <a href=\"https://ghost.org/\">Ghost</a> a go!</p>\n",
            "url": "https://mrvautin.com/the-best-free-blog-software/",
            "title": "The best free blog software",
            "summary": "The best free blog software",
            "date_modified": "2018-05-20T05:20:56.000Z"
        },
        {
            "id": "https://mrvautin.com/screenshot-to-clipboard-on-apple-mac-osx/",
            "content_html": "<p>To copy a portion of the screen to the clipboard, press Command-Control-Shift-4. A cross-hair cursor will appear and you can click and drag to select the area you wish to capture. When you release the mouse button, you can paste the screen shot to another application.</p>\n",
            "url": "https://mrvautin.com/screenshot-to-clipboard-on-apple-mac-osx/",
            "title": "Screenshot to clipboard on Apple Mac OSX",
            "summary": "Screenshot to clipboard on Apple Mac OSX",
            "date_modified": "2018-05-20T04:43:28.000Z"
        },
        {
            "id": "https://mrvautin.com/re-use-mongodb-database-connection-in-routes/",
            "content_html": "<p>Quite often when you are writing an application you will need access to one or more database connections. Maybe MongoDB for data storage and Redis for cache. You will need to re-use that database connection throughout your application. I'm going to go through a simple way of re-using the connection in modules, Express routes etc.</p>\n<h2 id=\"creating-the-helper\">Creating the helper</h2>\n<p>Firstly you will want to create your <code>db.js</code> file which will export some handy database related functions.</p>\n<p>File: <code>db.js</code></p>\n<pre><code class=\"language-javascript\">    <span class=\"hljs-keyword\">const</span> mongoClient = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;mongodb&#x27;</span>).MongoClient;\n    <span class=\"hljs-keyword\">const</span> mongoDbUrl = <span class=\"hljs-string\">&#x27;mongodb://127.0.0.1:27017&#x27;</span>;\n    <span class=\"hljs-keyword\">let</span> mongodb;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> <span class=\"hljs-title\">connect</span>(<span class=\"hljs-params\">callback</span>)</span>{\n        mongoClient.connect(mongoDbUrl, <span class=\"hljs-function\">(<span class=\"hljs-params\">err, db</span>) =&gt;</span> {\n            mongodb = db;\n            callback();\n        });\n    }\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> <span class=\"hljs-title\">get</span>(<span class=\"hljs-params\"></span>)</span>{\n        <span class=\"hljs-keyword\">return</span> mongodb;\n    }\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> <span class=\"hljs-title\">close</span>(<span class=\"hljs-params\"></span>)</span>{\n        mongodb.close();\n    }\n\n    <span class=\"hljs-built_in\">module</span>.exports = {\n        connect,\n        get,\n        close\n    };\n</code></pre>\n<p>After creating this file you can simply <code>require</code> it and you now have few functions at our disposal. <code>connect</code>, <code>get</code>, <code>close</code>.</p>\n<h2 id=\"connecting\">Connecting</h2>\n<p>File: <code>app.js</code></p>\n<p>You will then want to call <code>connect()</code> before your application starts and the server starts listening. Eg:</p>\n<pre><code class=\"language-javascript\">    db.connect(<span class=\"hljs-function\">() =&gt;</span> {\n        app.listen(process.env.PORT || <span class=\"hljs-number\">5555</span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\"></span>)</span>{\n            <span class=\"hljs-built_in\">console</span>.log(<span class=\"hljs-string\">`Listening`</span>);\n        });\n    });\n</code></pre>\n<p>Now you have access to your database connection anywhere in your application by simply requiring the <code>db.js</code> file and using the <code>get()</code> function.</p>\n<h2 id=\"using-the-connection\">Using the connection</h2>\n<p>File: <code>users.js</code> (routes file for example)</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">const</span> db = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;./db&#x27;</span>);\n\nrouter.get(<span class=\"hljs-string\">&#x27;/users&#x27;</span>, <span class=\"hljs-function\">(<span class=\"hljs-params\">req, res</span>) =&gt;</span> {\n\tdb.get().collection(<span class=\"hljs-string\">&#x27;users&#x27;</span>).find({}).toArray()\n\t.then(<span class=\"hljs-function\">(<span class=\"hljs-params\">users</span>) =&gt;</span> {\n            <span class=\"hljs-built_in\">console</span>.log(<span class=\"hljs-string\">&#x27;Users&#x27;</span>, users);\n        });\n});\n</code></pre>\n<p>It just makes everything much cleaner and easy to handle this way. I hope this helped you in some way.</p>\n",
            "url": "https://mrvautin.com/re-use-mongodb-database-connection-in-routes/",
            "title": "Nodejs - Re-use MongoDB database connection in routes",
            "summary": "Nodejs - Re-use MongoDB database connection in routes",
            "date_modified": "2018-04-12T20:55:22.000Z"
        },
        {
            "id": "https://mrvautin.com/dokku-could-not-read-from-remote-repository-on-digital-ocean/",
            "content_html": "<p>Firing up a digital ocean droplet with one-click dokku should be easy right? Yeah well if you get this error it's due to your SSH keys not being added correctly either when setting up the droplet or if you did it yourself.</p>\n<p>You simply need to run:</p>\n<p><code>cat ~/.ssh/id_rsa.pub | ssh root@droplet_ip_address &quot;sudo sshcommand acl-add dokku laptop&quot;</code></p>\n",
            "url": "https://mrvautin.com/dokku-could-not-read-from-remote-repository-on-digital-ocean/",
            "title": "Dokku - Could not read from remote repository on digital ocean",
            "summary": "Dokku - Could not read from remote repository on digital ocean",
            "date_modified": "2017-02-17T08:44:11.000Z"
        },
        {
            "id": "https://mrvautin.com/adding-new-lines-to-your-ifttt-recipes/",
            "content_html": "<p>Adding breaks or new lines to your ifttt recipes can be a difficult task. Facebook seems to be particularly picky with it's new line characters where standard new lines like <code>\\r</code> <code>\\r\\n</code> and <code>&lt;br&gt;</code> are ignored.</p>\n<p><strong>The solution</strong>:</p>\n<p><code>&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;</code></p>\n<p>No worries, glad I could help!</p>\n",
            "url": "https://mrvautin.com/adding-new-lines-to-your-ifttt-recipes/",
            "title": "Adding new lines to your IFTTT recipes",
            "summary": "Adding new lines to your IFTTT recipes",
            "date_modified": "2017-01-28T06:30:01.000Z"
        },
        {
            "id": "https://mrvautin.com/enabling-custom-domain-for-saas-application-on-heroku/",
            "content_html": "<p>If you are running a SaaS application on Heroku you might notice that it's difficult enabling the users of the SaaS application to bring their own custom domain using a DNS <code>CNAME</code>. When the request comes into Heroku the platform will return the &quot;No such application&quot; error. The Heroku support team suggests adding a custom domain to the Heroku dashboard for each SaaS user. I could see this getting out of hand so I decided to implement a proxy server to fix the issue.</p>\n<p>Firstly you will want to add your own wildcard custom domain to your Heroku application and also create a <code>CNAME</code> with your DNS provider.</p>\n<p>Adding your <code>CNAME</code> with your DNS provider to point to Heroku:</p>\n<p><strong>Hostname</strong>: *.mydomain.com<br>\n<strong>Path</strong>: my_heroku_app_name.herokuapp.com</p>\n<p>Adding your domain to the Heroku dashboard:</p>\n<p><strong>Domain Name</strong>: *.mydomain.com<br>\n<strong>DNS Target</strong>: my_heroku_app_name.herokuapp.com</p>\n<p>You will then want to setup your proxy server. I spun up a new <a href=\"https://m.do.co/c/d248e1e45937\">Digital Ocean</a> droplet and setup Nginx to proxy the requests.</p>\n<p>The Nginx config would look like this:</p>\n<pre><code class=\"language-bash\">server {\n    listen 80 default_server;\n\n    server_name proxy.mydomain.com;\n\n    location / {\n        proxy_set_header    Host <span class=\"hljs-variable\">$host</span>;\n        proxy_set_header    X-Real-IP <span class=\"hljs-variable\">$remote_addr</span>;\n        proxy_set_header    X-Forwarded-For <span class=\"hljs-variable\">$proxy_add_x_forwarded_for</span>;\n        proxy_set_header    Host <span class=\"hljs-variable\">$host</span>-customdomain.mydomain.com;\n        proxy_redirect      off;\n        proxy_pass          http://my_heroku_app_name.herokuapp.com;\n    }\n}\n</code></pre>\n<p>Basically what is happening is your Nginx server is adding the <code>Host</code> header and proxing the request onto Heroku. The Heroku router will then read the <code>Host</code> header and determine which application to select. It's then that your application will need to determine the domain in the request and serve the correct SaaS user.</p>\n<p>You will then need to setup an <code>A</code> DNS record with your DNS provider to point to the new proxy server:</p>\n<p><strong>Hostname</strong>: proxy.mydomain.com<br>\n<strong>Path</strong>: 192.168.0.1 (This IP is your <a href=\"https://m.do.co/c/d248e1e45937\">Digital Ocean</a> droplet IP)</p>\n<p>You will then want your users of your SaaS application who are wanting a custom domain to point their DNS to <code>proxy.mydomain.com</code>.</p>\n<p>Your Saas application will then need to get the <code>Host</code> header, remove -<code>customdomain.mydomain.com</code> and determine who the customer of your SaaS application is.</p>\n",
            "url": "https://mrvautin.com/enabling-custom-domain-for-saas-application-on-heroku/",
            "title": "Enabling custom domain for SaaS application on Heroku",
            "summary": "Enabling custom domain for SaaS application on Heroku",
            "date_modified": "2017-01-24T23:40:29.000Z"
        },
        {
            "id": "https://mrvautin.com/building-a-reliable-and-scalable-node-js-saas-application/",
            "content_html": "<p>The SaaS app we built is an FAQ/Knowledge base and support ticketing platform called ezyFAQ - <a href=\"https://www.ezyfaq.com\">www.ezyfaq.com</a></p>\n<p>Having built many Node.Js projects, this would be our first venture into building a scalable SaaS app. After our initial investigation on where we should start, we couldn't find much advice on where to start and things to look out for. We found vague articles on various projects built many years ago but nothing using modern tech, in particular Node.JS.</p>\n<p>We are intending this article to be helpful to anyone wanting to build a SaaS app using Node.Js.</p>\n<h2 id=\"hosting\">Hosting</h2>\n<p>Up until this project we built our apps on self managed Digital Ocean VM's. This was fine in isolation but we found it difficult to find any information on scaling and load balancing to grow with the app user base.</p>\n<p>We decided to go with a dedicated Node.Js host (Heroku) which used the Dyno type approach. This seemed like the best approach to easily scale as the customer base and load grows.</p>\n<h2 id=\"database\">Database</h2>\n<p>Generally our database of choice to pair with Node.JS is MongoDB. After trying and considering various other databases, we decided to stick with MongoDB.</p>\n<p>Hosting MongoDB yourself is easy enough but we wanted something more reliable with load balancing/redundancy, scaling and backups. There are various options from MongoDB Atlas, Compose.io, mLab etc. After some consideration, we went with mLab for easy of use, scalability and best price.</p>\n<h2 id=\"application-structure\">Application structure</h2>\n<p>This is where we spent most of our time trying to figure out the best approach. There are two parts to the app: the front and backend. The frontend is the part of the app which would see all the public traffic. Each customer of our app would have their own FAQ with a subdomain (and optional custom domain) which would see significant traffic. The backend is the management side for our customers where they would manage settings, content, style and more. The backend would receive minimal traffic in comparison to the public facing frontend and so would have much less of a need to scale.</p>\n<p>Instead of creating one big app we decided to split them out and run on seperate Heroku plans. This way we can scale the frontend easily whilst leaving the backend as it. It also means we can easily do maintenance, add features etc without affecting the public facing side of the app.</p>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>We learnt a lot. First of all, we learn't that making a standalone app into a SaaS is not as easy as it sounds. There are many different aspects which need to be considered and worked through. We found that scalability and being flexible was the key to our success and this is where we spent most of our time. We also found that doing everything and managing everything is not the always the best thing. Leave the server and DB hosting to a dedicated company to manage it for you. As a startup, you can't possibly be professional and perfect at everything. You can always bring services back in house as you grow and your available skill set grows too.</p>\n<p>We would love to hear feedback from others who have faced similar hurdles getting their SaaS app off the ground and how they dealt with them.</p>\n",
            "url": "https://mrvautin.com/building-a-reliable-and-scalable-node-js-saas-application/",
            "title": "Building a reliable and scalable Node.JS SaaS application",
            "summary": "Building a reliable and scalable Node.JS SaaS application",
            "date_modified": "2017-01-22T03:50:10.000Z"
        },
        {
            "id": "https://mrvautin.com/ezyfaq-an-easy-to-use-yet-beautiful-and-powerful-faq-knowledge-base/",
            "content_html": "<p><a href=\"https://www.ezyfaq.com\">ezyFAQ</a> is a very powerful yet affordable solution to setup a FAQ/knowledge base without all the complexities (and cost) of Zendesk and other solutions. Studies have shown that most customers would much prefer to quickly find the solution themselves rather than wait on an email response or make a phone call.</p>\n<p><a href=\"https://www.ezyfaq.com\">ezyFAQ</a> allows for customising your FAQ/knowledge base with branding, CSS and HTML. <a href=\"https://www.ezyfaq.com\">ezyFAQ</a> also allows you to bring your own domain for a seamless integration with your existing website - e.g: help.mydomain.com. The live search, analytics, responsive design (also beautiful on Tablets and Phones), pre-built themes and templates allow you to customise a little or a lot!</p>\n<p><a href=\"https://www.ezyfaq.com\">ezyFAQ</a> runs its own FAQ using the <a href=\"https://www.ezyfaq.com\">ezyFAQ</a> platform which you can view here: <a href=\"http://support.ezyfaq.com\">http://support.ezyfaq.com</a></p>\n<p>More information can be found at <a href=\"https://www.ezyfaq.com\">www.ezyfaq.com</a></p>\n",
            "url": "https://mrvautin.com/ezyfaq-an-easy-to-use-yet-beautiful-and-powerful-faq-knowledge-base/",
            "title": "ezyFAQ An easy-to-use yet beautiful and powerful FAQ/Knowledge base",
            "summary": "ezyFAQ An easy-to-use yet beautiful and powerful FAQ/Knowledge base",
            "date_modified": "2016-11-18T23:27:00.000Z"
        },
        {
            "id": "https://mrvautin.com/writing-your-first-node-js-module/",
            "content_html": "<p>This isn't meant to be an exhaustive guide on how to write an NPM module. This guide is meant to be a simple working example where you can see a basic working module and easily adapt this to create your own module.</p>\n<p>You can see the basic structure is really easy to understand. We are exposing the <code>multiply()</code> function as a public function by returning in the <code>module.exports</code>. The other function aptly named <code>nonPublic()</code> is called by the <code>multiply()</code> function but cannot be called publicly. More on this below.</p>\n<p>You can see our <code>multiply()</code> function takes two values, multiplies them and returns a label from our <code>nonPublic()</code> function, followed by our multiplied value. Easy!</p>\n<p>File: <code>multiply.js</code></p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-comment\">// require any modules</span>\n\n<span class=\"hljs-built_in\">module</span>.exports = {\n\t<span class=\"hljs-attr\">multiply</span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\">val1, val2, callback</span>)</span>{\n        <span class=\"hljs-keyword\">var</span> returnedValue = val1 * val2;\n\t\tcallback(<span class=\"hljs-literal\">null</span>, nonPublic() + returnedValue);\n\t}\n};\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> <span class=\"hljs-title\">nonPublic</span>(<span class=\"hljs-params\"></span>)</span>{\n    <span class=\"hljs-keyword\">return</span> <span class=\"hljs-string\">&#x27;Result: &#x27;</span>;\n}\n</code></pre>\n<hr>\n<p>File: <code>test.js</code></p>\n<p>Using our new module locally for testing is easy:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">var</span> mod = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;./module&#x27;</span>);\n\n<span class=\"hljs-built_in\">console</span>.log(mod.nonPublic());\n\nmod.multiply(<span class=\"hljs-number\">5</span>, <span class=\"hljs-number\">10</span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span>(<span class=\"hljs-params\">err, result</span>)</span>{\n    <span class=\"hljs-built_in\">console</span>.log(result);\n});\n</code></pre>\n<p>The first line requires our local module. <strong>Note: the <code>./</code> value for modules located in the same directory.</strong></p>\n<p>After we have required it we can go ahead and use it. First we call the <code>nonPublic()</code> function to show it doesn't work publicly (this outputs an error), then call the <code>multiply()</code> function.</p>\n<p>We pass in <code>5</code> and <code>10</code> to be multiplied together and we write the result to the console.</p>\n<p>To run our <code>test.js</code> script we simply run the following in our console and observe the output:</p>\n<p><code>node test.js</code></p>\n<h4 id=\"conclusion\">Conclusion</h4>\n<p>This is a really basic module which outlines the basic steps to get started on writing your first NPM module.</p>\n<p>One of my <strong>slightly (hardly)</strong> more advanced (has options etc) modules <code>metaget</code> can be found here as further reading: <a href=\"https://github.com/mrvautin/metaget\">https://github.com/mrvautin/metaget</a></p>\n",
            "url": "https://mrvautin.com/writing-your-first-node-js-module/",
            "title": "Writing your first Node.js module",
            "summary": "Writing your first Node.js module",
            "date_modified": "2016-09-03T01:14:52.000Z"
        },
        {
            "id": "https://mrvautin.com/ensure-express-app-started-before-tests/",
            "content_html": "<p>Seems simple enough but when running tests, I ran into a problem where Mocha/Supertest was not waiting for my Express App to fully start running tests.</p>\n<p>The relatively easy way to overcome this is to use an event emitter in your Express app and wait for that to complete before starting your tests. This doesn't appear to be documented anywhere obvious.</p>\n<p>You will need to setup the event emitter in your Express app which is the final step before assuming the app has started and is ready. In my case, I had made the DB connection etc and now the call to <code>app.listen</code> was my final event.</p>\n<p>Here is an example:</p>\n<pre><code class=\"language-javascript\">app.listen(app_port, app_host, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\"></span>) </span>{\n    <span class=\"hljs-built_in\">console</span>.log(<span class=\"hljs-string\">&#x27;App has started&#x27;</span>);\n    app.emit(<span class=\"hljs-string\">&quot;appStarted&quot;</span>);\n});\n</code></pre>\n<p>The specific line is:</p>\n<pre><code class=\"language-javascript\">app.emit(<span class=\"hljs-string\">&quot;appStarted&quot;</span>);\n</code></pre>\n<p>This creates an event which we can wait on called <code>appStarted</code> (this can be changed to whatever you want).</p>\n<p>Next we need to wait for this event in our Mocha/Supertest tests (<code>test.js</code>).</p>\n<p>First we will <code>require</code> our Express app. Note: <code>app</code> is my main Express file, some people use <code>server.js</code> and this value would then become <code>require('../server')</code>:</p>\n<pre><code class=\"language-javascript\">app = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;../app&#x27;</span>);\n</code></pre>\n<p>We then need to create a Supertest agent using our Express instance:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">var</span> request = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;supertest&quot;</span>);\n<span class=\"hljs-keyword\">var</span> agent = request.agent(app);\n</code></pre>\n<p>Then we wait for our Express event using <code>before()</code>:</p>\n<pre><code class=\"language-javascript\">before(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\">done</span>) </span>{\n    app.on(<span class=\"hljs-string\">&quot;adminMongoStarted&quot;</span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span>(<span class=\"hljs-params\"></span>)</span>{\n        done();\n    });\n});\n</code></pre>\n<p>Then we can kick off all our tests. A full test example:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">var</span> request = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;supertest&quot;</span>);\n<span class=\"hljs-keyword\">var</span> assert = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;chai&#x27;</span>).assert;\n\napp = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;../app&#x27;</span>);\n<span class=\"hljs-keyword\">var</span> agent = request.agent(app);\n\nbefore(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\">done</span>) </span>{\n    app.on(<span class=\"hljs-string\">&quot;appStarted&quot;</span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span>(<span class=\"hljs-params\"></span>)</span>{\n        done();\n    });\n});\n\ndescribe(<span class=\"hljs-string\">&quot;Add config&quot;</span>,<span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span>(<span class=\"hljs-params\"></span>)</span>{\n    it(<span class=\"hljs-string\">&quot;Add a new connection&quot;</span>,<span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span>(<span class=\"hljs-params\">done</span>)</span>{\n        agent\n            .post(<span class=\"hljs-string\">&quot;/add_config&quot;</span>)\n            .expect(<span class=\"hljs-number\">200</span>)\n            .expect(<span class=\"hljs-string\">&quot;Config successfully added&quot;</span>, done);\n    });\n});\n</code></pre>\n",
            "url": "https://mrvautin.com/ensure-express-app-started-before-tests/",
            "title": "Ensure Express App has started before running Mocha/Supertest tests",
            "summary": "Ensure Express App has started before running Mocha/Supertest tests",
            "date_modified": "2016-06-19T05:12:19.000Z"
        },
        {
            "id": "https://mrvautin.com/markdowntables-convert-your-html-tables-into-markdown-syntax-online/",
            "content_html": "<p>markdownTables is an online tool which enables you to paste in your HTML table code and convert it to Markdown table syntax.</p>\n<p><a href=\"http://markdowntables.mrvautin.com\">markdownTables</a></p>\n<p><img src=\"/content/images/2016/05/markdownTables.png\" alt=\"\"></p>\n",
            "url": "https://mrvautin.com/markdowntables-convert-your-html-tables-into-markdown-syntax-online/",
            "title": "markdownTables - Convert your HTML tables into Markdown syntax online",
            "summary": "markdownTables - Convert your HTML tables into Markdown syntax online",
            "date_modified": "2016-05-17T06:47:08.000Z"
        },
        {
            "id": "https://mrvautin.com/authorstats-get-your-npm-package-download-statistics-in-an-easy-to-read-command-line-table/",
            "content_html": "<p><code>authorStats</code> fetches your daily/weekly/monthly download stats for all your authored NPM packages and outputs a nice table right in your command line.</p>\n<h3 id=\"installation\">Installation</h3>\n<p>It's best to install the package globally:</p>\n<p><code>npm install author-stats -g</code></p>\n<h3 id=\"usage\">Usage</h3>\n<p><code>authorStats &lt;npm username&gt;</code></p>\n<p>Where <code>&lt;npm username&gt;</code> is the username on the NPM website. My profile is: <code>https://www.npmjs.com/~mrvautin</code> and username is <code>mrvautin</code>.</p>\n<p>A nice command line table with the daily, weekly and monthly download numbers of all your packages will be output to your terminal.</p>\n<p>Note: If you have a lot of packages you will need to be patient while <code>authorStats</code> fetches the data.</p>\n",
            "url": "https://mrvautin.com/authorstats-get-your-npm-package-download-statistics-in-an-easy-to-read-command-line-table/",
            "title": "authorStats - Get your NPM package download statistics in an easy to read command line table",
            "summary": "authorStats - Get your NPM package download statistics in an easy to read command line table",
            "date_modified": "2016-05-06T10:37:13.000Z"
        },
        {
            "id": "https://mrvautin.com/expresscart-a-nodejs-shopping-cart-application/",
            "content_html": "<p>expressCart is a Shopping Cart built with <a href=\"https://nodejs.org/\">Nodejs</a> and <a href=\"http://expressjs.com/\">ExpressJS</a>. The application has <a href=\"https://paypal.com\">PayPal</a> Express Checkout, <a href=\"https://stripe.com\">Stripe</a> checkout and Authorize.Net built-in. expressCart uses <a href=\"https://www.mongodb.com/\">MongoDB</a> database backend.</p>\n<p>The application is designed to be easy to use and install and based on search for simplicity rather than nested categories. Simply search for what you want and select from the results. expressCart uses powerful <a href=\"http://lunrjs.com\">lunr.js</a> to index the products and enable the best search results.</p>\n<p><strong>Website</strong>: <a href=\"https://expresscart.markmoffat.com/\">https://expresscart.markmoffat.com/</a></p>\n<p><strong>Demo</strong>: <a href=\"https://demo.expresscart.markmoffat.com\">https://expresscart-demo.markmoffat.com</a></p>\n<h3 id=\"features\">Features</h3>\n<ul>\n<li><strong>Payments</strong>: expressCart has built in <a href=\"https://paypal.com\">PayPal</a> Express Checkout or <a href=\"https://stripe.com\">Stripe</a> checkout.</li>\n<li><strong>Search</strong>: expressCart is a search based Shopping Cart backed by <a href=\"https://github.com/olivernn/lunr.js/\">Lunr.js</a> indexing to create the best possible results on searches.</li>\n<li><strong>Backend</strong>: expressCart uses <a href=\"https://www.mongodb.com/\">MongoDB</a> for a database.</li>\n<li><strong>Design</strong>: expressCart has a simple flat and responsive design.</li>\n<li><strong>Responsive</strong>: expressCart is built using Bootstrap, allowing it to be responsive and work on all devices.</li>\n<li><strong>Themes</strong>: expressCart allows for custom themes to style the cart exactly how you like it.</li>\n</ul>\n<h3 id=\"screenshots\">Screenshots</h3>\n<p>Homepage:\n<img src=\"/content/images/2020/01/expressCart-homepage.png\" alt=\"Homepage\"></p>\n<p>Admin manage settings:\n<img src=\"/content/images/2020/03/expressCart-admin-settings.png\" alt=\"Admin manage settings\"></p>\n<p>Popout cart:\n<img src=\"/content/images/2020/01/expressCart-popout-cart.png\" alt=\"Popout cart\"></p>\n<p>Dashboard:\n<img src=\"/content/images/2020/03/expressCart-admin-dashboard.png\" alt=\"Dashboard\"></p>\n<h3 id=\"running-in-production\">Running in production</h3>\n<p>Using <a href=\"https://github.com/Unitech/pm2\">PM2</a> is the easiest and best option for running production websites.\nSee the <a href=\"https://github.com/Unitech/pm2\">PM2</a> for more information or a short guide here: <a href=\"/running-nodejs-applications-in-production-forever-vs-supervisord-vs-pm2/\">https://mrvautin.com/running-nodejs-applications-in-production-forever-vs-supervisord-vs-pm2/</a>.</p>\n",
            "url": "https://mrvautin.com/expresscart-a-nodejs-shopping-cart-application/",
            "title": "expressCart - A Nodejs Shopping Cart application",
            "summary": "expressCart - A Nodejs Shopping Cart application",
            "date_modified": "2016-04-29T05:19:49.000Z"
        },
        {
            "id": "https://mrvautin.com/ghoststrap-a-minimalist-and-responsive-bootstrap-theme-for-the-ghost-blogging-platform/",
            "content_html": "<p>Upon setting up my Ghost blog, I wanted a themewhich was compatible with Bootstrap as I'm familiar with the layout and it's rock solid in terms of responsive design. I was surprised to find that either the Bootstrap themes was really old and out of date or were way over the top and not a good starting point to add my touches.</p>\n<p>This pushed me to design <code>ghostStrap</code> which can easily be used as a starting point for anyone wanting to create a theme using the Bootstrap standard.</p>\n<h4 id=\"installation\">Installation</h4>\n<p>Some commands may need <code>sudo</code></p>\n<ol>\n<li>From the root of your Ghost install: <code>cd content/themes/</code></li>\n<li><code>git clone https://github.com/mrvautin/ghostStrap.git</code></li>\n<li>Restart Ghost</li>\n<li>Visit the admin panel: <a href=\"http://localhost:2368/ghost\">http://localhost:2368/ghost</a></li>\n<li>Select <code>General</code></li>\n<li>Select <code>ghostStrap</code> from the <code>Theme</code> dropdown</li>\n<li>Have fun</li>\n</ol>\n<p>Please leave a comment if you use the theme or have any feedback.</p>\n<h4 id=\"screenshots\">Screenshots</h4>\n<p><strong>Homepage</strong></p>\n<p><img src=\"/content/images/ghoststrap/homepage.png\" alt=\"Homepage\" title=\"Homepage\"></p>\n<p><strong>Single post</strong></p>\n<p><img src=\"/content/images/ghoststrap/singlepost.png\" alt=\"Single Post\" title=\"Single Post\"></p>\n<p><strong>Menu</strong></p>\n<p><img src=\"/content/images/ghoststrap/menu.png\" alt=\"Menu\" title=\"Menu\"></p>\n<p><strong>Mobile layout</strong></p>\n<p><img src=\"/content/images/ghoststrap/mobilelayout.png\" alt=\"Mobile layout\" title=\"Mobile layout\"></p>\n<p><strong>Menu</strong></p>\n<p><img src=\"/content/images/ghoststrap/mobilelayoutmenu.png\" alt=\"Mobile layout menu\" title=\"Mobile layout menu\"></p>\n",
            "url": "https://mrvautin.com/ghoststrap-a-minimalist-and-responsive-bootstrap-theme-for-the-ghost-blogging-platform/",
            "title": "ghostStrap - A minimalist and responsive Bootstrap theme for the Ghost blogging platform",
            "summary": "ghostStrap - A minimalist and responsive Bootstrap theme for the Ghost blogging platform",
            "date_modified": "2016-04-18T07:34:48.000Z"
        },
        {
            "id": "https://mrvautin.com/how-to-add-search-functionality-to-your-ghost-blog/",
            "content_html": "<p>Adding search to your Ghost blog is relatively simple but requires a small amount of skill to edit your theme files. You can see how search works on the homepage of this <a href=\"https://mrvautin.com\">blog</a>.</p>\n<p>First of all, you need to turn on the Ghost Public API (which by default is turned off). You will want to jump into your Ghost admin <code>www.myblog.com/ghost</code>, select <code>Labs</code> from the menu, scroll to the bottom and check the box <code>Public API</code>.</p>\n<p>Now this is turned on, our code will be able to interact with the API to index and search posts.</p>\n<p>We are going to use the following Github repository by <a href=\"https://github.com/Windyo\">Windyo</a> here: <a href=\"https://github.com/Windyo/ghostHunter/\">https://github.com/Windyo/ghostHunter/</a> this is a Fork of the popular <a href=\"https://github.com/jamalneufeld/ghostHunter\">ghostHunter</a> module but has been updated to use the Ghost API, rather than using and hacking RSS feeds. <code>Ghosthunter</code> uses the extremely powerful <a href=\"https://github.com/olivernn/lunr.js\">Lunr</a> library to index your posts and provide the best, weighted keyword search results.</p>\n<p>You will need to download the file <code>jquery.ghostHunter.min.js</code> from the Github repository and add it to your theme: <code>/content/themes/mytheme/assets/js/</code>.</p>\n<p>You will then need to add a reference to that file in: <code>/content/themes/mytheme/default.hbs</code></p>\n<pre><code class=\"language-javascript\">{% raw %}\n &lt;script type=<span class=\"hljs-string\">&quot;text/javascript&quot;</span> src=<span class=\"hljs-string\">&quot;{{asset &quot;</span>js/jquery.ghostHunter.min.js<span class=\"hljs-string\">&quot;}}&quot;</span>&gt;&lt;/script&gt;\n {% endraw %}\n</code></pre>\n<p><strong>Note: Add it at the bottom of the file after the jQuery reference</strong></p>\n<p>Once you have done that you can start adding the search box to your page(s).</p>\n<p>You will need some javascript which calls the Ghosthunter module to display the results of the search. You will need to add the following code to your <code>/content/themes/mytheme/assets/js/index.js</code> file.</p>\n<p><strong>There are various options on the Ghosthunter module. I've decided to display results as they are typed and have set the <code>onKeyUp</code> to <code>true</code> and have chosen to hide the number of results by setting <code>displaySearchInfo</code> to false. Check the <a href=\"https://github.com/Windyo/ghostHunter/\">Github repository</a> for more options.</strong></p>\n<pre><code class=\"language-javascript\">$(<span class=\"hljs-string\">&quot;.search-results&quot;</span>).addClass(<span class=\"hljs-string\">&quot;results-hide&quot;</span>);\n$(<span class=\"hljs-string\">&quot;#search-field&quot;</span>).ghostHunter({\n    <span class=\"hljs-attr\">results</span>: <span class=\"hljs-string\">&quot;#search-results&quot;</span>,\n    <span class=\"hljs-attr\">onKeyUp</span>: <span class=\"hljs-literal\">true</span>,\n    <span class=\"hljs-attr\">displaySearchInfo</span>: <span class=\"hljs-literal\">false</span>,\n    <span class=\"hljs-attr\">result_template</span> : <span class=\"hljs-string\">&quot;&lt;a href=&#x27;{{link}}&#x27;&gt;&lt;li class=&#x27;list-group-item&#x27;&gt;{{title}}&lt;/li&gt;&lt;/a&gt;&quot;</span>,\n    <span class=\"hljs-attr\">before</span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span>(<span class=\"hljs-params\"></span>)</span>{ \n        $(<span class=\"hljs-string\">&quot;.search-results&quot;</span>).removeClass(<span class=\"hljs-string\">&quot;results-hide&quot;</span>);\n    }\n}); \n</code></pre>\n<p><strong>Note: My theme is using Twitter Bootstrap so you will see references to <code>list-group-item</code> etc which you can remove and add your own CSS styling.</strong></p>\n<p>Next thing you need to do is add some simple CSS to your <code>/content/themes/mytheme/assets/js/screen.css</code> to format the search and results box.</p>\n<pre><code class=\"language-css\"><span class=\"hljs-selector-class\">.search-box</span>{\n    <span class=\"hljs-attribute\">margin-bottom</span>: <span class=\"hljs-number\">10px</span>;\n}\n\n<span class=\"hljs-selector-class\">.search-results</span> {\n    <span class=\"hljs-attribute\">position</span>:absolute;\n    <span class=\"hljs-attribute\">z-index</span>: <span class=\"hljs-number\">1000</span>;\n}\n\n<span class=\"hljs-selector-class\">.search-button</span>{\n    <span class=\"hljs-attribute\">background-color</span>: <span class=\"hljs-number\">#1B95E0</span>;\n    <span class=\"hljs-attribute\">color</span>: white;\n}\n\n<span class=\"hljs-selector-class\">.results-hide</span>{\n    <span class=\"hljs-attribute\">display</span>: none;\n}\n</code></pre>\n<p><strong>Note: You can edit styling as you wish.</strong></p>\n<p>Lastly you will need to add the search box to your template file: <code>/content/themes/mytheme/index.hbs</code>. You can also add this to your <code>post.hbs</code> view too if you wish.</p>\n<pre><code class=\"language-html\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;row&quot;</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;search-box col-xs-12 col-sm-12 col-md-4 col-md-offset-4 col-lg-4 col-lg-offset-4&quot;</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;input-group&quot;</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input</span> <span class=\"hljs-attr\">type</span>=<span class=\"hljs-string\">&quot;text&quot;</span> <span class=\"hljs-attr\">id</span>=<span class=\"hljs-string\">&quot;search-field&quot;</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;form-control input-lg&quot;</span> <span class=\"hljs-attr\">placeholder</span>=<span class=\"hljs-string\">&quot;Search for...&quot;</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;input-group-btn&quot;</span>&gt;</span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;btn btn-default search-button btn-lg&quot;</span> <span class=\"hljs-attr\">type</span>=<span class=\"hljs-string\">&quot;button&quot;</span>&gt;</span>Search!<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">button</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">span</span>&gt;</span>               \n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;search-results col-xs-12 col-sm-12 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2&quot;</span> &gt;</span>    \n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul</span> <span class=\"hljs-attr\">id</span>=<span class=\"hljs-string\">&quot;search-results&quot;</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;search-results col-md-12&quot;</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;list-group&quot;</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">ul</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">section</span>&gt;</span>\n</code></pre>\n<p>Please let me know in the comments what you think.</p>\n",
            "url": "https://mrvautin.com/how-to-add-search-functionality-to-your-ghost-blog/",
            "title": "How to add search functionality to your Ghost blog",
            "summary": "How to add search functionality to your Ghost blog",
            "date_modified": "2016-04-17T00:34:38.000Z"
        },
        {
            "id": "https://mrvautin.com/how-to-setup-https-on-your-ghost-blog-without-redirect-loop/",
            "content_html": "<p>If you are wanting to setup your Ghost blog URL to be <code>HTTPS</code> (SSL), you will need to ensure your Web Server is sending the correct Headers to Ghost. Failing to do so can cause your Blog to go into a endless redirect loop and fail to work.</p>\n<p>The production section of your Ghost <code>config.js</code> will look something like this:</p>\n<pre><code class=\"language-javascript\">production: {\n\t<span class=\"hljs-attr\">url</span>: <span class=\"hljs-string\">&#x27;https://mrvautin.com&#x27;</span>,\n\t<span class=\"hljs-attr\">mail</span>: {},\n\t<span class=\"hljs-attr\">database</span>: {}\n}\n\n</code></pre>\n<p>Depending on your web server the setting is slightly different. We are going to cover off <code>Apache</code> and <code>Nginx</code> as they are most popular.</p>\n<h5 id=\"for-nginx\">For Nginx</h5>\n<p>A simple <code>Nginx</code> config would look like:</p>\n<pre><code class=\"language-nginx\"><span class=\"hljs-section\">server</span> {\n\t<span class=\"hljs-attribute\">listen</span> <span class=\"hljs-number\">443</span> ssl;\n\t<span class=\"hljs-attribute\">server_name</span> mrvautin.com www.mrvautin.com;\n\t<span class=\"hljs-comment\"># SSL STUFF</span>\n\n\t<span class=\"hljs-attribute\">location</span> / {\n\t\t<span class=\"hljs-attribute\">proxy_set_header</span>        X-Real-IP $remote_addr;\n\t\t<span class=\"hljs-attribute\">proxy_set_header</span>        Host    $http_host;\n\t\t<span class=\"hljs-attribute\">proxy_pass</span>              http://127.0.0.1:2368;\n\t\t<span class=\"hljs-attribute\">proxy_set_header</span>        X-Forwarded-Proto $scheme;\n\t}\n}\n</code></pre>\n<p>The important line above is:</p>\n<p><code>proxy_set_header        X-Forwarded-Proto $scheme;</code></p>\n<p>This line ensures the Header which Ghost reads has the correct protocol set.</p>\n<h5 id=\"for-apache\">For Apache</h5>\n<p>A simple <code>Apache</code> virtual host config would look like:</p>\n<pre><code class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">VirtualHost</span> *<span class=\"hljs-attr\">:443</span>&gt;</span>\n    RequestHeader set X-Forwarded-Proto &quot;https&quot;\n    ProxyPreserveHost On\n    ServerName mrvautin.com\n\n    SSLEngine On\n    SSLCertificateFile /etc/apache2/ssl/server.crt\n    SSLCertificateKeyFile /etc/apache2/ssl/server.key\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Location</span>/&gt;</span>\n        SSLRequireSSL\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">Location</span>&gt;</span>\n\n    ProxyPass / http://127.0.0.1:2368\n    ProxyPassReverse / http://127.0.0.1:2368\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">VirtualHost</span>&gt;</span>\n</code></pre>\n<p>The important line above is:</p>\n<p><code>RequestHeader set X-Forwarded-Proto &quot;https&quot;</code></p>\n<p>This line ensures the Header which Ghost reads has the correct protocol set.</p>\n",
            "url": "https://mrvautin.com/how-to-setup-https-on-your-ghost-blog-without-redirect-loop/",
            "title": "How to setup HTTPS on your Ghost blog and avoid redirect loop",
            "summary": "How to setup HTTPS on your Ghost blog and avoid redirect loop",
            "date_modified": "2016-04-15T00:05:00.000Z"
        },
        {
            "id": "https://mrvautin.com/how-to-change-the-excerpt-text-to-html-formatting/",
            "content_html": "<p>The Casper theme by default has an excerpt with all HTML tags / formatting removed. You can change this in your theme by editing the <code>/content/themes/mytheme/partials/loop.hbs</code> file of your theme.</p>\n<p>In the <code>loop.hbs</code> file you will see:</p>\n<pre><code class=\"language-handlebars\"><span class=\"xml\">{% raw %}\n</span><span class=\"hljs-template-variable\">{{<span class=\"hljs-name\">excerpt</span> <span class=\"hljs-attr\">words</span>=<span class=\"hljs-string\">&quot;26&quot;</span>}}</span><span class=\"xml\">\n{% endraw %}\n</span></code></pre>\n<p>You will need to change the word <code>excerpt</code> to <code>content</code>. The new code will be:</p>\n<pre><code class=\"language-handlebars\"><span class=\"xml\">{% raw %}\n</span><span class=\"hljs-template-variable\">{{<span class=\"hljs-name\">content</span> <span class=\"hljs-attr\">words</span>=<span class=\"hljs-string\">&quot;26&quot;</span>}}</span><span class=\"xml\">\n{% endraw %}\n</span></code></pre>\n<p>If you are wanting to change the length (amount of words) of the excerpt please see <a href=\"https://mrvautin.com/how-to-change-the-excerpt-length-in-your-ghost-theme/\">here</a>.</p>\n",
            "url": "https://mrvautin.com/how-to-change-the-excerpt-text-to-html-formatting/",
            "title": "How to change the post excerpt of your Ghost theme to HTML",
            "summary": "How to change the post excerpt of your Ghost theme to HTML",
            "date_modified": "2016-04-12T00:50:52.000Z"
        },
        {
            "id": "https://mrvautin.com/how-to-change-the-excerpt-length-in-your-ghost-theme/",
            "content_html": "<p>Changing the post excerpt length (teaser text) of your theme is relatively simple. You will need to edit the <code>/content/themes/mytheme/partials/loop.hbs</code></p>\n<p>When opening your <code>loop.hbs</code> file you will see code like the this:</p>\n<p>You can change the default Casper value of 26 to any value you want:</p>\n<p>You can play around and change this value and see what length best suits your writing style and theme.</p>\n",
            "url": "https://mrvautin.com/how-to-change-the-excerpt-length-in-your-ghost-theme/",
            "title": "How to change the post excerpt length in your Ghost theme",
            "summary": "How to change the post excerpt length in your Ghost theme",
            "date_modified": "2016-04-12T00:26:52.000Z"
        },
        {
            "id": "https://mrvautin.com/metaget/",
            "content_html": "<p>A Node.js module to fetch HTML meta tags (including Open Graph) from a remote URL</p>\n<h2 id=\"installation\">Installation</h2>\n<p><code>npm install metaget --save</code></p>\n<h2 id=\"usage\">Usage</h2>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">var</span> metaget = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;metaget&quot;</span>);\nmetaget.fetch(<span class=\"hljs-string\">&#x27;https://wordpress.com&#x27;</span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\">err, meta_response</span>) </span>{\n\t<span class=\"hljs-keyword\">if</span>(err){\n\t\t<span class=\"hljs-built_in\">console</span>.log(err);\n\t}<span class=\"hljs-keyword\">else</span>{\n\t\t<span class=\"hljs-built_in\">console</span>.log(meta_response);\n\t}\n});\n</code></pre>\n<p>Response will be a Javascript Object containing all the meta tags from the URL. All tags are output in the example above. Some tags with illegal characters can be accessed by:</p>\n<pre><code class=\"language-javascript\">meta_response[<span class=\"hljs-string\">&quot;og:title&quot;</span>];\n</code></pre>\n<h2 id=\"options\">Options</h2>\n<p>It's possible to set any HTTP headers in the request. This can be done by specifying them as options in the call. If no options are provided the only default header is a User-Agent of &quot;request&quot;.</p>\n<p>This is how you would specify a &quot;User-Agent&quot; of a Google Bot:</p>\n<pre><code class=\"language-javascript\"><span class=\"hljs-keyword\">var</span> metaget = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;metaget&quot;</span>);\nmetaget.fetch(<span class=\"hljs-string\">&#x27;https://wordpress.com&#x27;</span>,{<span class=\"hljs-attr\">headers</span>:{<span class=\"hljs-string\">&quot;User-Agent&quot;</span>: <span class=\"hljs-string\">&quot;Googlebot&quot;</span>}}, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function</span> (<span class=\"hljs-params\">err, meta_response</span>) </span>{\n\t<span class=\"hljs-keyword\">if</span>(err){\n\t\t<span class=\"hljs-built_in\">console</span>.log(err);\n\t}<span class=\"hljs-keyword\">else</span>{\n\t\t<span class=\"hljs-built_in\">console</span>.log(meta_response);\n\t}\n});\n</code></pre>\n<h2 id=\"contributing\">Contributing</h2>\n<ol>\n<li>Fork it!</li>\n<li>Create your feature branch: <code>git checkout -b my-new-feature</code></li>\n<li>Commit your changes: <code>git commit -am 'Add some feature'</code></li>\n<li>Push to the branch: <code>git push origin my-new-feature</code></li>\n<li>Submit a pull request :D</li>\n</ol>\n",
            "url": "https://mrvautin.com/metaget/",
            "title": "metaget - Nodejs module to fetch remote Meta Tags (including Open Graph) from URL",
            "summary": "metaget - Nodejs module to fetch remote Meta Tags (including Open Graph) from URL",
            "date_modified": "2016-04-11T06:02:50.000Z"
        },
        {
            "id": "https://mrvautin.com/adminmongo/",
            "content_html": "<p>adminMongo is a Web based user interface (GUI) to handle all your MongoDB connections/databases needs. adminMongo is fully responsive and should work on a range of devices.</p>\n<blockquote>\n<p>adminMongo connection information (including username/password) is stored unencrypted in a config file, it is not recommended to run this application on a production or public facing server without proper security considerations.</p>\n</blockquote>\n<h2 id=\"installation\">Installation</h2>\n<ol>\n<li>Clone Repository: <code>git clone https://github.com/mrvautin/adminMongo.git &amp;&amp; cd adminMongo</code></li>\n<li>Install dependencies: <code>npm install</code></li>\n<li>Start application: <code>npm start</code></li>\n<li>Visit <a href=\"http://127.0.0.1:1234\">http://127.0.0.1:1234</a> in your browser</li>\n</ol>\n<h2 id=\"features\">Features</h2>\n<ul>\n<li>Manage from a connection level for easy access to multiple databases</li>\n<li>Create/Delete databases</li>\n<li>Create/Delete/Edit collection</li>\n<li>Create/Delete/Edit documents</li>\n<li>Create/Delete indexes</li>\n<li>Query documents</li>\n<li>Collection statistics</li>\n<li>Export collections in JSON format</li>\n</ul>\n<h3 id=\"limitations\">Limitations</h3>\n<ul>\n<li>Documents need to have an &quot;_id&quot; value which is a string, integer, or MongoDB ObjectId. Documents using Composite ID indexing is currently not supported.</li>\n</ul>\n<h4 id=\"configuration\">Configuration</h4>\n<p>adminMongo will listen on host: <code>localhost</code> and  port: <code>1234</code> by default.\nThis can be overwritten by adding a config file in <code>/config/app.json</code>. The config file can also override the default 5 docs per page.\nThe config file options are:</p>\n<pre><code class=\"language-json\">{\n    <span class=\"hljs-attr\">&quot;app&quot;</span>: {\n        <span class=\"hljs-attr\">&quot;host&quot;</span>: <span class=\"hljs-string\">&quot;10.0.0.1&quot;</span>,\n        <span class=\"hljs-attr\">&quot;port&quot;</span>: <span class=\"hljs-number\">4321</span>,\n        <span class=\"hljs-attr\">&quot;docs_per_page&quot;</span>: <span class=\"hljs-number\">15</span>\n    }\n}\n</code></pre>\n<h2 id=\"usage\">Usage</h2>\n<h5 id=\"create-a-connection\">Create a connection</h5>\n<p>After visiting <a href=\"http://127.0.0.1:1234\">http://127.0.0.1:1234</a> you will be presented with a connection screen. You need to give your connection a unique name as a reference when using adminMongo and a MongoDB formatted connection string. The format of a MongoDB connection string can form: <code>mongodb://&lt;user&gt;:&lt;password&gt;@127.0.0.1:&lt;port&gt;/&lt;db&gt;</code> where specifying to the <code>&lt;db&gt;</code> level is optional. For more information on MongoDB connection strings, see the <a href=\"http://docs.mongodb.org/manual/reference/connection-string/\">official MongoDB documentation</a>.</p>\n<p>Note: The connection can be either local or remote hosted on VPS or MongoDB service such as MongoLab.</p>\n<h5 id=\"connection%2Fdatabase-admin\">Connection/Database admin</h5>\n<p>After opening your newly created connection, you are able to see all database objects associated with your connection. Here you can create/delete collections, create/delete users and see various stats for your database.</p>\n<h5 id=\"collections\">Collections</h5>\n<p>After selecting your collection from the &quot;Database Objects&quot; menu, you will be presented with the collections screen. Here you can see documents in pagination form, create new documents, search documents, delete, edit documents and view/add indexes to your collection.</p>\n<h5 id=\"searching-documents\">Searching documents</h5>\n<p>You can search documents using the <code>Search documents</code> button on the collections screen. You will need to enter the key (field name) and value. Eg: key = &quot;_id&quot; and value = &quot;569ff81e0077663d78a114ce&quot;.</p>\n<blockquote>\n<p>You can clear your search by clicking the <code>Reset</code> button on the collections screen.</p>\n</blockquote>\n<h5 id=\"documents\">Documents</h5>\n<p>Adding and editing documents is done using a JSON syntax highlighting control.</p>\n<h5 id=\"indexes\">Indexes</h5>\n<p>Indexes can be added from the collection screen. Please see the <a href=\"https://docs.mongodb.org/manual/indexes/\">official MongoDB documentation</a> on adding indexes.</p>\n<h2 id=\"contributing\">Contributing</h2>\n<ol>\n<li>Fork it!</li>\n<li>Create your feature branch: <code>git checkout -b my-new-feature</code></li>\n<li>Commit your changes: <code>git commit -am 'Add some feature'</code></li>\n<li>Push to the branch: <code>git push origin my-new-feature</code></li>\n<li>Submit a pull request :D</li>\n</ol>\n",
            "url": "https://mrvautin.com/adminmongo/",
            "title": "adminMongo",
            "summary": "adminMongo",
            "date_modified": "2016-04-04T00:05:00.000Z"
        },
        {
            "id": "https://mrvautin.com/winterboard-theme-ios9-common-bundle-id-icon-list/",
            "content_html": "<p>Common App Bundle ID list (case sensitive)</p>\n<p>These are used in your <strong>mytheme.theme/Bundles</strong> folder.</p>\n<div class=\"table-responsive\">\n<table class=\"table table-condensed\">\n<thead>\n<tr>\n<th>App Name</th>\n<th>Bundle ID</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1Password</td>\n<td>com.agilebits.onepassword-ios</td>\n</tr>\n<tr>\n<td>500px</td>\n<td>com.500px</td>\n</tr>\n<tr>\n<td>9gag</td>\n<td>com.9gag.ios.mobile</td>\n</tr>\n<tr>\n<td>Activator</td>\n<td>libactivator</td>\n</tr>\n<tr>\n<td>Airbnb</td>\n<td>com.airbnb.app</td>\n</tr>\n<tr>\n<td>Amazon</td>\n<td>com.amazon.Amazon</td>\n</tr>\n<tr>\n<td>App Store</td>\n<td>com.apple.AppStore</td>\n</tr>\n<tr>\n<td>Ask Fm</td>\n<td>fm.ask.askfm</td>\n</tr>\n<tr>\n<td>BiteSMS</td>\n<td>com.bitesms</td>\n</tr>\n<tr>\n<td>Calculator</td>\n<td>com.apple.calculator</td>\n</tr>\n<tr>\n<td>Calendar</td>\n<td>com.apple.mobilecal</td>\n</tr>\n<tr>\n<td>Camera +</td>\n<td>com.taptaptap.cloudphotos</td>\n</tr>\n<tr>\n<td>Camera</td>\n<td>com.apple.camera</td>\n</tr>\n<tr>\n<td>Chase Mobile</td>\n<td>com.chase</td>\n</tr>\n<tr>\n<td>Circle the Dot</td>\n<td>com.ketchapp.circlethedot</td>\n</tr>\n<tr>\n<td>Clock</td>\n<td>com.apple.mobiletimer</td>\n</tr>\n<tr>\n<td>CNN</td>\n<td>com.cnn.iphone</td>\n</tr>\n<tr>\n<td>Compass</td>\n<td>com.apple.compass</td>\n</tr>\n<tr>\n<td>Contacts</td>\n<td>com.apple.MobileAddressBook</td>\n</tr>\n<tr>\n<td>Digg</td>\n<td>com.digg.Digg</td>\n</tr>\n<tr>\n<td>Dropbox</td>\n<td>com.getdropbox.Dropbox</td>\n</tr>\n<tr>\n<td>Ebay</td>\n<td>com.ebay.iphone</td>\n</tr>\n<tr>\n<td>Edline</td>\n<td>com.alecgorge.Brebeuf-Edline</td>\n</tr>\n<tr>\n<td>Engadget</td>\n<td>com.aol.engadget</td>\n</tr>\n<tr>\n<td>ESPN SportsCenter</td>\n<td>com.espn.ScoreCenter</td>\n</tr>\n<tr>\n<td>eTrade</td>\n<td>com.etrade.mobileproiphone</td>\n</tr>\n<tr>\n<td>ETSY</td>\n<td>com.etsy.etsyforios</td>\n</tr>\n<tr>\n<td>Evernote</td>\n<td>com.evernote.Evernote</td>\n</tr>\n<tr>\n<td>Evernote</td>\n<td>com.evernote.iPhone.Evernote</td>\n</tr>\n<tr>\n<td>Facebook Groups</td>\n<td>com.facebook.Groups</td>\n</tr>\n<tr>\n<td>Facebook Page Admin</td>\n<td>com.facebook.PageAdminApp</td>\n</tr>\n<tr>\n<td>Facebook Paper</td>\n<td>com.facebook.Paper</td>\n</tr>\n<tr>\n<td>Facebook</td>\n<td>com.facebook.Facebook</td>\n</tr>\n<tr>\n<td>Facetime</td>\n<td>com.apple.facetime</td>\n</tr>\n<tr>\n<td>FB Messenger</td>\n<td>com.facebook.Messenger</td>\n</tr>\n<tr>\n<td>Find my iPhone</td>\n<td>com.apple.mobileme.fmip1</td>\n</tr>\n<tr>\n<td>Firefox</td>\n<td>org.mozilla.ios.Firefox</td>\n</tr>\n<tr>\n<td>Flappy Bird</td>\n<td>com.dotgears.flap</td>\n</tr>\n<tr>\n<td>Fleksy</td>\n<td>com.syntellia.Fleksy</td>\n</tr>\n<tr>\n<td>Foap</td>\n<td>com.foap.foap</td>\n</tr>\n<tr>\n<td>Game Center</td>\n<td>com.apple.gamecenter</td>\n</tr>\n<tr>\n<td>Gamestop</td>\n<td>com.gamestop.powerup</td>\n</tr>\n<tr>\n<td>Google +</td>\n<td>com.google.GooglePlus</td>\n</tr>\n<tr>\n<td>Google Chrome</td>\n<td>com.google.chrome.ios</td>\n</tr>\n<tr>\n<td>Google Chromecast</td>\n<td>com.google.Chromecast</td>\n</tr>\n<tr>\n<td>Google Docs</td>\n<td>com.google.Docs</td>\n</tr>\n<tr>\n<td>Google Drive</td>\n<td>com.google.Drive</td>\n</tr>\n<tr>\n<td>Google Gmail</td>\n<td>com.google.Gmail</td>\n</tr>\n<tr>\n<td>Google Inbox</td>\n<td>com.google.inbox</td>\n</tr>\n<tr>\n<td>Google Maps</td>\n<td>com.google.Maps</td>\n</tr>\n<tr>\n<td>Google Photos</td>\n<td>com.google.photos</td>\n</tr>\n<tr>\n<td>Google Search</td>\n<td>com.google.GoogleMobile</td>\n</tr>\n<tr>\n<td>Google Translate</td>\n<td>com.google.Translate</td>\n</tr>\n<tr>\n<td>Health</td>\n<td>com.apple.Health</td>\n</tr>\n<tr>\n<td>iBooks</td>\n<td>com.apple.iBooks</td>\n</tr>\n<tr>\n<td>iFile</td>\n<td>eu.heinelt.ifile</td>\n</tr>\n<tr>\n<td>iMessage</td>\n<td>com.apple.MobileSMS</td>\n</tr>\n<tr>\n<td>iMovie</td>\n<td>com.apple.iMovie</td>\n</tr>\n<tr>\n<td>Instagram</td>\n<td>com.burbn.instagram</td>\n</tr>\n<tr>\n<td>iTunes Connect</td>\n<td>com.apple.itunesconnect.mobile</td>\n</tr>\n<tr>\n<td>iTunes Store</td>\n<td>com.apple.MobileStore</td>\n</tr>\n<tr>\n<td>Kickstarter</td>\n<td>com.kickstarter.kickstarter</td>\n</tr>\n<tr>\n<td>LinkedIn</td>\n<td>com.linkedin.LinkedIn</td>\n</tr>\n<tr>\n<td>Mail</td>\n<td>com.apple.mobilemail</td>\n</tr>\n<tr>\n<td>Make it Rain</td>\n<td>com.SpaceInch.LoveOfMoney</td>\n</tr>\n<tr>\n<td>Maps</td>\n<td>com.apple.Maps</td>\n</tr>\n<tr>\n<td>Medium</td>\n<td>com.medium.reader</td>\n</tr>\n<tr>\n<td>ModMyi</td>\n<td>com.modmyi.ModMyi</td>\n</tr>\n<tr>\n<td>Music</td>\n<td>com.apple.Music</td>\n</tr>\n<tr>\n<td>Myspace</td>\n<td>com.myspace.iPhone</td>\n</tr>\n<tr>\n<td>Netflix</td>\n<td>com.netflix.Netflix</td>\n</tr>\n<tr>\n<td>Notes</td>\n<td>com.apple.mobilenotes</td>\n</tr>\n<tr>\n<td>Ookla Speedtest</td>\n<td>com.ookla.speedtest</td>\n</tr>\n<tr>\n<td>Oovoo</td>\n<td>com.oovoo.iphone.free</td>\n</tr>\n<tr>\n<td>Outlook</td>\n<td>com.microsoft.Office.Outlook</td>\n</tr>\n<tr>\n<td>outube</td>\n<td>com.youtube.ios.youtube</td>\n</tr>\n<tr>\n<td>Pandora</td>\n<td>com.pandora.pandora</td>\n</tr>\n<tr>\n<td>Passbook</td>\n<td>com.apple.Passbook</td>\n</tr>\n<tr>\n<td>Paypal</td>\n<td>com.yourcompany.PPClient</td>\n</tr>\n<tr>\n<td>Phonto</td>\n<td>com.youthhr.Phonto Y</td>\n</tr>\n<tr>\n<td>PhotoMath</td>\n<td>com.microblink.PhotoMath Xbox</td>\n</tr>\n<tr>\n<td>Photos</td>\n<td>com.apple.mobileslideshow</td>\n</tr>\n<tr>\n<td>Photoshop Express</td>\n<td>com.adobe.PSMobile</td>\n</tr>\n<tr>\n<td>Piano Tiles</td>\n<td>com.umonistudio.tapTile</td>\n</tr>\n<tr>\n<td>Podcasts</td>\n<td>com.apple.podcasts</td>\n</tr>\n<tr>\n<td>Quizup</td>\n<td>com.plainvanillacorp.quizup</td>\n</tr>\n<tr>\n<td>Reddit</td>\n<td>com.tyanya.reddit</td>\n</tr>\n<tr>\n<td>Reeder</td>\n<td>ch.reeder</td>\n</tr>\n<tr>\n<td>Release Slow Shutter</td>\n<td>com.cogitap.SlowShutter</td>\n</tr>\n<tr>\n<td>Reminders</td>\n<td>com.apple.reminders</td>\n</tr>\n<tr>\n<td>Remote Mouse</td>\n<td>com.remotemouse.remoteMouse</td>\n</tr>\n<tr>\n<td>Remote</td>\n<td>com.apple.Remote</td>\n</tr>\n<tr>\n<td>Safari</td>\n<td>com.apple.mobilesafari</td>\n</tr>\n<tr>\n<td>Settings</td>\n<td>com.apple.Preferences</td>\n</tr>\n<tr>\n<td>Skype</td>\n<td>com.skype.skype</td>\n</tr>\n<tr>\n<td>Smartglass</td>\n<td>com.microsoft.xboxavatars</td>\n</tr>\n<tr>\n<td>Snapchat</td>\n<td>com.toyopagroup.picaboo</td>\n</tr>\n<tr>\n<td>SoundHound</td>\n<td>com.melodis.midomi</td>\n</tr>\n<tr>\n<td>Spotify</td>\n<td>com.spotify.client</td>\n</tr>\n<tr>\n<td>Square Cash</td>\n<td>com.squareup.cash</td>\n</tr>\n<tr>\n<td>Stay in the Line</td>\n<td>com.six8t.StayInTheLine</td>\n</tr>\n<tr>\n<td>Stocks</td>\n<td>com.apple.stocks</td>\n</tr>\n<tr>\n<td>Stop Motion</td>\n<td>com.cateater.funapps.stopmotion</td>\n</tr>\n<tr>\n<td>Swing Copters</td>\n<td>com.dotgears.swing</td>\n</tr>\n<tr>\n<td>Teamviewer</td>\n<td>com.teamviewer.teamviewer</td>\n</tr>\n<tr>\n<td>Terminal</td>\n<td>com.googlecode.mobileterminal.Terminal</td>\n</tr>\n<tr>\n<td>Testflight</td>\n<td>com.apple.TestFlight</td>\n</tr>\n<tr>\n<td>Things</td>\n<td>com.culturedcode.ThingsTouch</td>\n</tr>\n<tr>\n<td>Tinder</td>\n<td>com.cardify.tinder</td>\n</tr>\n<tr>\n<td>Tips</td>\n<td>com.apple.tips</td>\n</tr>\n<tr>\n<td>Tumblr</td>\n<td>com.tumblr.tumblr1Password</td>\n</tr>\n<tr>\n<td>Tweetbot 3</td>\n<td>com.tapbots.Tweetbot3</td>\n</tr>\n<tr>\n<td>Tweetbot 4</td>\n<td>com.tapbots.Tweetbot4</td>\n</tr>\n<tr>\n<td>Tweetbot iPad</td>\n<td>com.tapbots.TweetbotPad</td>\n</tr>\n<tr>\n<td>Tweetbot</td>\n<td>com.tapbots.Tweetbot</td>\n</tr>\n<tr>\n<td>Twitter</td>\n<td>com.atebits.Tweetie2</td>\n</tr>\n<tr>\n<td>Ultimate Guitar Tabs</td>\n<td>com.ultimateguitar.tabs100</td>\n</tr>\n<tr>\n<td>Viber</td>\n<td>com.viber</td>\n</tr>\n<tr>\n<td>Videos</td>\n<td>com.apple.videos</td>\n</tr>\n<tr>\n<td>Vidgets</td>\n<td>com.lesscode.widgetcenter</td>\n</tr>\n<tr>\n<td>Vimeo</td>\n<td>com.vimeo</td>\n</tr>\n<tr>\n<td>Voice Memos</td>\n<td>com.apple.VoiceMemos</td>\n</tr>\n<tr>\n<td>Weather</td>\n<td>com.apple.weather</td>\n</tr>\n<tr>\n<td>WhatsApp</td>\n<td>net.whatsapp.WhatsApp</td>\n</tr>\n<tr>\n<td>Winterboard</td>\n<td>com.saurik.Winterboard</td>\n</tr>\n<tr>\n<td>WWDC</td>\n<td>developer.apple.wwdc</td>\n</tr>\n<tr>\n<td>WWDC</td>\n<td>developer.apple.wwdc-Release</td>\n</tr>\n<tr>\n<td>Yahoo Weather</td>\n<td>com.yahoo.weather</td>\n</tr>\n<tr>\n<td>YouTube</td>\n<td>com.google.ios.youtube</td>\n</tr>\n</tbody>\n</table>\n<p>Common icon names and sizes (px):</p>\n<table class=\"table table-condensed\">\n<thead>\n<tr>\n<th>Icon name</th>\n<th>Size</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>AppIcon76x76~ipad.png</td>\n<td>76x76</td>\n</tr>\n<tr>\n<td>[email protected]</td>\n<td>58x58</td>\n</tr>\n<tr>\n<td>[email protected]</td>\n<td>80x80</td>\n</tr>\n<tr>\n<td>[email protected]</td>\n<td>120x120</td>\n</tr>\n<tr>\n<td>AppIcon76x76@2x~ipad.png</td>\n<td>152x152</td>\n</tr>\n<tr>\n<td>[email protected]</td>\n<td>87x87</td>\n</tr>\n<tr>\n<td>[email protected]</td>\n<td>120x120</td>\n</tr>\n<tr>\n<td>[email protected]</td>\n<td>180x180</td>\n</tr>\n</tbody>\n</table>\n</div>",
            "url": "https://mrvautin.com/winterboard-theme-ios9-common-bundle-id-icon-list/",
            "title": "Winterboard theme iOS9 common Bundle ID / Icon list",
            "summary": "Winterboard theme iOS9 common Bundle ID / Icon list",
            "date_modified": "2015-11-21T21:48:00.000Z"
        },
        {
            "id": "https://mrvautin.com/cydia-live-nba-scores-right-on-your-iphone-lockscreen/",
            "content_html": "<p>I admit, I'm addicted to following the NBA scores live. The problem I was having was either leaving my iPhone unlocked on the ESPN or NBA app and killing my battery or unlocking my phone (pin/fingerprint) every 5 seconds to see the scores! This is where the &quot;NBA Lockscreen scores&quot; package (Free on Modmyi repo) comes in. You can simply hit the home button to bring up your lockscreen and the updated scores and right there waiting.</p>\n<p>[Cydia link](cydia://search/nba lockscreen scores)</p>\n",
            "url": "https://mrvautin.com/cydia-live-nba-scores-right-on-your-iphone-lockscreen/",
            "title": "Cydia - Live NBA scores right on your iPhone lockscreen",
            "summary": "Cydia - Live NBA scores right on your iPhone lockscreen",
            "date_modified": "2015-11-16T21:54:00.000Z"
        },
        {
            "id": "https://mrvautin.com/easy-way-of-moving-notes-from-iphone-to-icloud/",
            "content_html": "<p>You may experience an issue where older notes are considered &quot;ON MY IPHONE&quot; and not backed up to iCloud you have two options. 1: manually copy all notes into new ones which by default sit on iCloud. 2: follow the steps below.</p>\n<ol>\n<li>Select &quot;Notes&quot; section below &quot;ON MY IPHONE&quot;.</li>\n</ol>\n<p><img src=\"/content/images/notes1.jpeg\" alt=\"notes on my iPhone\"></p>\n<ol start=\"2\">\n<li>Select &quot;edit&quot; (top right), select notes manually or select &quot;Move All&quot; (bottom left)</li>\n</ol>\n<p><img src=\"/content/images/notes2.jpeg\" alt=\"select notes\"></p>\n<ol start=\"3\">\n<li>Select &quot;Notes&quot; under &quot;ICLOUD&quot; section to copy notes.</li>\n</ol>\n<p><img src=\"/content/images/notes3.jpeg\" alt=\"select iCloud\"></p>\n<p>NOTE: The app may not update the number of notes until it's closed and reopened.</p>\n",
            "url": "https://mrvautin.com/easy-way-of-moving-notes-from-iphone-to-icloud/",
            "title": "Easy way of moving notes from iPhone to iCloud",
            "summary": "Easy way of moving notes from iPhone to iCloud",
            "date_modified": "2015-10-02T10:21:00.000Z"
        },
        {
            "id": "https://mrvautin.com/openkb-an-open-source-nodejs-knowledge-base-application/",
            "content_html": "<p>openKB is an open source Markdown based Knowledge base application (FAQ) built with <a href=\"https://nodejs.org/\">Nodejs</a> and <a href=\"http://expressjs.com/\">ExpressJS</a>. The application uses an embedded database (<a href=\"https://github.com/louischatriot/nedb\">nedb</a>) for easy installation without a full Database server.\nThe application is designed to be easy to use and install and based around search rather than nested categories. Simply search for what you want and select from the results.</p>\n<p>Demo: <a href=\"http://openkb.mrvautin.com\">http://openkb.mrvautin.com</a></p>\n<h3 id=\"installation\">Installation</h3>\n<ol>\n<li>Clone Repository: <code>git clone https://github.com/mrvautin/openKB.git &amp;&amp; cd openKB</code></li>\n<li>Install dependencies: <code>npm install</code></li>\n<li>Start application: <code>npm start</code></li>\n<li>Go to  <a href=\"http://127.0.0.1:4444\">http://127.0.0.1:4444</a> in your browser</li>\n</ol>\n<h3 id=\"features\">Features</h3>\n<ul>\n<li><strong>Search</strong>: openKB is a search based Knowledgebase (FAQ) backed by <a href=\"https://github.com/olivernn/lunr.js/\">Lunr.js</a> indexing to create the best possible results on searches.</li>\n<li><strong>Backend</strong>: openKB uses the pure javascript <a href=\"https://github.com/louischatriot/nedb\">nedb</a> embedded database. This means no external databases need to be setup.</li>\n<li><strong>Design</strong>: openKB is meant to be simple flat design. With that said, openKB is very customisable by adding your CSS file to <code>/public/stylesheets/</code> and adding a link in <code>/views/layouts/layout.hbs</code> you can add your own styling and graphics.</li>\n<li><strong>Responsive</strong>: openKB is built using Bootstrap allowing it to be responsive and work on all devices. The <code>admin</code> can be a little difficult editing Markdown on smaller screens.</li>\n<li><strong>Mermaid</strong>: openKB allows for <a href=\"http://knsv.github.io/mermaid/\">Mermaid</a> charts in articles.</li>\n<li><strong>Editor</strong>: openKB uses Markdown-it which is based off the <a href=\"http://spec.commonmark.org/\">CommonMark spec</a>. This allows for the very best Markdown experience.</li>\n<li><strong>Image management</strong>: openKB allows for drag and drop of images into articles. The image is automatically uploaded to the server in the background. Google Chrome users can also paste images directly from the clipboard.</li>\n</ul>\n<h3 id=\"screenshots\">Screenshots</h3>\n<p><img src=\"/content/images/openkb/homepage.png\" alt=\"Homepage\">\n<img src=\"/content/images/openkb/editor.png\" alt=\"Editor\">\n<img src=\"/content/images/openkb/articleview.png\" alt=\"Article view\">\n<img src=\"/content/images/openkb/articlefiltering.png\" alt=\"Article filtering\">\n<img src=\"/content/images/openkb/files.png\" alt=\"Files\"></p>\n<h3 id=\"admin\">Admin</h3>\n<p>Visit: <a href=\"http://127.0.0.1:4444/login\">http://127.0.0.1:4444/login</a></p>\n<p>A new user form will be shown where a user can be created.</p>\n<h3 id=\"config\">Config</h3>\n<p>There are are a few configurations that can be made which are held in <code>/routes/config.js</code>. If any values have been changed the app will need to be restarted.</p>\n<h3 id=\"running-in-production\">Running in production</h3>\n<p>Using <a href=\"https://github.com/Unitech/pm2\">PM2</a> seems to be the easiest and best option for running production websites.\nSee the <a href=\"https://github.com/Unitech/pm2\">PM2</a> for more information or a short guide here: <a href=\"http://mrvautin.com/Running-Nodejs-applications-in-production-forever-vs-supervisord-vs-pm2\">http://mrvautin.com/Running-Nodejs-applications-in-production-forever-vs-supervisord-vs-pm2</a>.</p>\n",
            "url": "https://mrvautin.com/openkb-an-open-source-nodejs-knowledge-base-application/",
            "title": "openKB - Open Source Nodejs Markdown based knowledge base (FAQ) app",
            "summary": "openKB - Open Source Nodejs Markdown based knowledge base (FAQ) app",
            "date_modified": "2015-08-02T23:55:00.000Z"
        },
        {
            "id": "https://mrvautin.com/running-nodejs-applications-in-production-forever-vs-supervisord-vs-pm2/",
            "content_html": "<p>There are a few aspects to think of when setting up a Nodejs application in production. I'm going to cover off <code>Process management</code> and <code>Webservers</code>.</p>\n<h3 id=\"process-management\">Process management</h3>\n<p>One of the aspects you need to think about is keeping your app alive. When running PHP, when your app process crashes or server restarts the application <strong>WILL</strong> come back online automatically. With Nodejs, if the process crashes or the server restarts the process will <strong>NOT</strong> start itself. This is where a process manager comes into play, luckily there are a few good ones to choose from.</p>\n<p>I will run through some of them and detail their pros and cons but to summarise: I like <a href=\"https://github.com/Unitech/pm2\">PM2</a> for easy setup of personal projects but I definitely recommend setting up <a href=\"https://github.com/systemd/systemd\">systemd</a> for a proper production environment.</p>\n<h4 id=\"supervisord-(link)\">supervisord (<a href=\"https://github.com/Supervisor/supervisor\">Link</a>)</h4>\n<p><strong>Pros</strong></p>\n<ul>\n<li>Mature software</li>\n<li>Works on many different environments</li>\n</ul>\n<p><strong>Cons</strong></p>\n<ul>\n<li>Not Nodejs specific</li>\n<li>Harder to setup</li>\n<li>limited options</li>\n</ul>\n<p><a href=\"https://blog.risingstack.com/operating-node-in-production\">SETUP GUIDE</a></p>\n<h4 id=\"forever-(link)\">forever (<a href=\"https://github.com/foreverjs/forever\">Link</a>)</h4>\n<p><strong>Pros</strong></p>\n<ul>\n<li>Mature software (7.5k Github stars)</li>\n<li>Works on many different environments</li>\n<li>Easy to setup</li>\n</ul>\n<p><strong>Cons</strong></p>\n<ul>\n<li>I found it was unreliable recovering my Nodejs apps</li>\n<li>Had issues with apps being auto started after a system reboot</li>\n<li>Limited options (at the time of writing)</li>\n</ul>\n<p><a href=\"https://expressjs.com/en/advanced/pm.html#forever\">SETUP GUIDE</a></p>\n<h4 id=\"pm2%3A-my-pick-for-personal-(link)\">pm2: my pick for personal (<a href=\"https://github.com/Unitech/pm2\">Link</a>)</h4>\n<p><strong>Pros</strong></p>\n<ul>\n<li>Mature software (12.5k Github stars)</li>\n<li>Can be used with an enterprise (paid) add-on service called <a href=\"https://keymetrics.io/\">Keymetrics</a></li>\n<li>Works on many different environments</li>\n<li>Super easy to setup</li>\n<li>Many different options to scale apps in cluster mode etc</li>\n<li>Command <code>pm2 list</code> give an easy to read table of all apps</li>\n</ul>\n<p><strong>Cons</strong></p>\n<ul>\n<li>A little difficult setting up as a non root user</li>\n<li>None that I've found so far. Rock solid.</li>\n</ul>\n<p><a href=\"https://expressjs.com/en/advanced/pm.html#pm2\">SETUP GUIDE</a></p>\n<h4 id=\"systemd%3A-my-pick-for-proper-applications-(link)\">SystemD: my pick for proper applications (<a href=\"https://github.com/systemd/systemd\">Link</a>)</h4>\n<p><strong>Pros</strong></p>\n<ul>\n<li>Mature software</li>\n<li>Is the default process manager on most linux environments</li>\n<li>Easy to setup</li>\n<li>Rock solid and proven software</li>\n<li>Can also run and mange other processes like Databases</li>\n</ul>\n<p><strong>Cons</strong></p>\n<ul>\n<li>None that I've found. Rock solid for production environments.</li>\n</ul>\n<p><a href=\"https://expressjs.com/en/advanced/pm.html#systemd\">SETUP GUIDE</a></p>\n<h3 id=\"webserver\">Webserver</h3>\n<p>I'm not even going to suggest others, I'm a Nginx man through and through and this in my opinion is the best and only choice in running a Nodejs webserver.</p>\n<p>Here is a short guide on setting up Nginx for your Nodejs app:</p>\n<p>Firstly need to install Nginx. Eg: Ubuntu: <code>$ sudo apt-get install nginx</code></p>\n<p>You the want to create the config for your application</p>\n<p><code>$ sudo nano /etc/nginx/sites-available/myapp</code></p>\n<p>The following is a very basic config to run your application. Basically it will listen for requests to <code>mydomain.com</code> on HTTP and forward those requests to our app (running with a process manager above) on port <code>4444</code>. You will need to change that port to whatever port your app is running/listening on.</p>\n<pre><code class=\"language-nginx\"><span class=\"hljs-section\">server</span> {\n    <span class=\"hljs-attribute\">listen</span> <span class=\"hljs-number\">80</span>;\n    <span class=\"hljs-attribute\">server_name</span> mydomain.com;\n\n    <span class=\"hljs-attribute\">location</span> / {\n        <span class=\"hljs-attribute\">proxy_pass</span> http://localhost:4444;\n        <span class=\"hljs-attribute\">proxy_http_version</span> <span class=\"hljs-number\">1</span>.<span class=\"hljs-number\">1</span>;\n        <span class=\"hljs-attribute\">proxy_set_header</span> Upgrade $http_upgrade;\n        <span class=\"hljs-attribute\">proxy_set_header</span> Connection <span class=\"hljs-string\">&#x27;upgrade&#x27;</span>;\n        <span class=\"hljs-attribute\">proxy_set_header</span> Host $host;\n        <span class=\"hljs-attribute\">proxy_cache_bypass</span> $http_upgrade;\n    }\n}\n</code></pre>\n<p>You can then save this file and test your Nginx config with:</p>\n<p><code>$ nginx -t</code></p>\n<p>All going well, you should get something like this:</p>\n<pre><code class=\"language-bash\">nginx: the configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf <span class=\"hljs-built_in\">test</span> is successful\n</code></pre>\n<p>If not, check the error and adjust your config to resolve.</p>\n<p>After a successful test, you now need to reload the new config into Nginx. You can either restart Nginx (will cause short downtime to all apps on server) or reload the config only. Best choice is to reload.</p>\n<p>Reload: <code>$ service nginx reload</code></p>\n<p>Restart: <code>$ service nginx restart</code></p>\n<p>Thats it! You should be able to visit your app at: <a href=\"http:mydomain.com\">http:mydomain.com</a></p>\n",
            "url": "https://mrvautin.com/running-nodejs-applications-in-production-forever-vs-supervisord-vs-pm2/",
            "title": "Running Nodejs applications in production forever vs supervisord vs pm2",
            "summary": "Running Nodejs applications in production forever vs supervisord vs pm2",
            "date_modified": "2015-05-04T10:23:00.000Z"
        },
        {
            "id": "https://mrvautin.com/adding-facebook-open-graph-metadata-to-your-website/",
            "content_html": "<p>It is a good idea for the sake of SEO to ensure your website has all the necessary Meta tags. This ensures the search engines and other services can crawl or interact with your website in an efficient manner.</p>\n<p>Some of the Meta tags you will want to set are called <a href=\"http://ogp.me/\">Open Graph</a> Metadata. When someone shares a link to your website on Facebook, you are telling Facebook what title, description, image etc you want to show in a persons feed. This means when someone shares a status with a URL to your website, Facebook will look at the URL and pull all the Open Graph Metadata in order to show the title, description, and images etc.</p>\n<p>All Metadata should be found within the <code>&lt;head&gt;</code> tag of your HTML document. The basic code of a Metadata is:</p>\n<pre><code>&lt;meta property=&quot;property_value&quot; content=&quot;content_value&quot;/&gt;\n</code></pre>\n<p>Where <code>property_value</code> is the actual Metadata we want to set and <code>content_value</code> is the actual value you would like.</p>\n<p>A list of Open Graph properties can be found here: <a href=\"http://ogp.me/\">http://ogp.me/</a></p>\n<p>The main ones you want to concentrate on are:</p>\n<h4 id=\"property%3A-og%3Aurl\">Property: og:url</h4>\n<p>The URL of the object being embedded into Facebook. This URL needs to be unique as it is used to collate Likes and shares on the object. The URL shouldn't include any session variables or GET parameters.</p>\n<p><strong>Example:</strong></p>\n<pre><code>&lt;meta property=&quot;og:url&quot; content=&quot;http://mrvautin.com/Adding-Facebook-Open-Graph-Metadata-to-your-website&quot;/&gt;\n</code></pre>\n<h4 id=\"property%3A-og%3Atitle\">Property: og:title</h4>\n<p>The title, headline or name of the object/article. This is shown when the URL/object is embedded into Facebook.</p>\n<p><strong>Example:</strong></p>\n<pre><code>&lt;meta property=&quot;og:title&quot; content=&quot;Adding Facebook Open Graph Metadata to your website&quot;/&gt;\n</code></pre>\n<h4 id=\"property%3A-og%3Adescription\">Property: og:description</h4>\n<p>A two sentence description/summary of the article/URL.</p>\n<p><strong>Example:</strong></p>\n<pre><code>&lt;meta property=&quot;og:description&quot; content=&quot;A short two sentence description of the article.&quot;/&gt;\n</code></pre>\n<h4 id=\"property%3A-og%3Aimage\">Property: og:image</h4>\n<p>Here you can include a link to an image you want to show when a URL to your website is shared. Facebook recommends an image at least 600x315 pixels but recommends using a larger image and letting them scale it accordingly. They recommend using an image with a 1.91:1 aspect ratio to avoid cropping. Note: images cannot exceed 5MB in size.</p>\n<p><strong>Example:</strong></p>\n<pre><code>&lt;meta property=&quot;og:image&quot; content=&quot;http://mrvautin.com/path_to_image.png&quot;/&gt;\n</code></pre>\n<h4 id=\"property%3A-og%3Atype\">Property: og:type</h4>\n<p>This is the type of URL being shared. Facebook outlines a long list of <a href=\"https://developers.facebook.com/docs/reference/opengraph/\">og:type</a> options but for a general website/blog you will want to use <code>article</code>.</p>\n<p><strong>Example:</strong></p>\n<pre><code>&lt;meta property=&quot;og:type&quot;   content=&quot;article&quot; /&gt;\n</code></pre>\n<h4 id=\"full-example\">Full example</h4>\n<pre><code>&lt;html&gt;\n&lt;head&gt;\n&lt;meta property=&quot;og:url&quot; content=&quot;http://mrvautin.com/Adding-Facebook-Open-Graph-Metadata-to-your-website&quot;/&gt;\n&lt;meta property=&quot;og:title&quot; content=&quot;Adding Facebook Open Graph Metadata to your website&quot;/&gt;\n&lt;meta property=&quot;og:description&quot; content=&quot;Adding Facebook Open Graph Metadata to your website&quot;/&gt;\n&lt;meta property=&quot;og:image&quot; content=&quot;http://mrvautin.com/path_to_image.png&quot;/&gt;\n&lt;meta property=&quot;og:type&quot; content=&quot;article&quot; /&gt;\n&lt;/head&gt;\n&lt;body&gt;\n      Content\n&lt;/body&gt;\n&lt;/html&gt;\n</code></pre>\n",
            "url": "https://mrvautin.com/adding-facebook-open-graph-metadata-to-your-website/",
            "title": "Adding Facebook Open Graph Metadata to your website",
            "summary": "Adding Facebook Open Graph Metadata to your website",
            "date_modified": "2014-12-31T21:44:00.000Z"
        },
        {
            "id": "https://mrvautin.com/antlers/",
            "content_html": "<p>A light weight blogging platform built on Node.js and Express. The <strong>antlers</strong> platform is designed to have all the necessary features to get a blog up and running, with minimal fuss and beautiful clean design throughout. Best of all, it's free!</p>\n<p><strong>antlers</strong> allows for easy templating (themes) using the <a href=\"http://handlebarsjs.com\">Handlebars</a> templating engine and includes a few themes out of the box.</p>\n<p>To get an idea of how your blog will look, take a look around! This blog is powered by <strong>antlers</strong>.</p>\n<h3 id=\"installation\">Installation</h3>\n<p><strong>Using: <a href=\"https://www.npmjs.com/package/antlers\">npm</a></strong></p>\n<p>or</p>\n<p><strong>Manual:</strong></p>\n<ol>\n<li>Install Node.js for your relevant server - There is a nice guide here: <a href=\"http://howtonode.org/how-to-install-nodejs\">http://howtonode.org/how-to-install-nodejs</a></li>\n<li>Download <strong>antlers</strong> from here: <a href=\"https://github.com/mrvautin/antlers\">https://github.com/mrvautin/antlers</a></li>\n<li>Extract the files and enter the directory via Command/Terminal</li>\n<li>Run <code>npm install</code> as an administrator (eg: sudo might be required)</li>\n<li>Then start the blog using <code>node app.js</code></li>\n<li>You're done! You can then view the blog by opening <a href=\"http://localhost:3333\">http://localhost:3333</a> in a browser</li>\n</ol>\n<h3 id=\"admin\">Admin</h3>\n<p>You can enter the admin panel of your newly created blog by visiting the following URL in your browser: <a href=\"http://localhost:3333/admin\">http://localhost:3333/admin</a>. The default user login is: <em>[email protected]</em> and password is: <em>password1</em>. After logging in, you can change the email (username) and password using the &quot;Users&quot; menu.</p>\n<hr/>\nFeel free to report any bugs on GitHub and give any feedback/suggestions by commenting below.\n",
            "url": "https://mrvautin.com/antlers/",
            "title": "Antlers",
            "summary": "Antlers",
            "date_modified": "2014-12-29T21:58:00.000Z"
        },
        {
            "id": "https://mrvautin.com/fun_plug-install-mediatomb-on-dns-320/",
            "content_html": "<p>Mediatomb is apparently pre-installed.. It doesn't seem to be on my NAS.</p>\n<p>The easiest way to install Mediatomb is via Optware.</p>\n<p>To install Optware you simply need to run:</p>\n<pre><code># wget http://wolf-u.li/u/233-O/ffp/start/optware.sh\n# chmod a+x /ffp/start/optware.sh\n# /ffp/start/optware.sh start\n</code></pre>\n<p>You can then install Mediatomb by running:</p>\n<pre><code># /opt/bin/ipkg install mediatomb\n</code></pre>\n<p>Then copy the Mediatomb startup script to &quot;start&quot;:</p>\n<pre><code># cp /opt/etc/init.d/mediatomb /ffp/start/mediatomb.sh\n</code></pre>\n<p>Then set the correct permissions on the &quot;mediatomb.sh file:</p>\n<pre><code># chmod a+x /ffp/start/mediatomb.sh\n</code></pre>\n<p>You need to change one of the Mediatomb configs to allow autostart:</p>\n<pre><code># vi /opt/etc/default/mediatomb\n</code></pre>\n<p>Ensure <em>MT_ENABLE=true</em></p>\n<p>You can now start Mediatomb by:</p>\n<pre><code># sh /ffp/start/mediatomb.sh start\n</code></pre>\n<p>You can now browse Mediatomb via the Web Interface:</p>\n<pre><code>http://localhost:4915\n</code></pre>\n",
            "url": "https://mrvautin.com/fun_plug-install-mediatomb-on-dns-320/",
            "title": "fun_plug install Mediatomb on dns-320",
            "summary": "fun_plug install Mediatomb on dns-320",
            "date_modified": "2013-10-06T22:00:00.000Z"
        },
        {
            "id": "https://mrvautin.com/adjust-stereo-clock-on-2006-to-2012-toyota-corolla/",
            "content_html": "<p>Adjusting the clock on the 2006 to 2011 Corolla is not documented anywhere in the manual. I stumbled across how to do it by pushing all the buttons. The process to adjust is not logical and so I figured I would document it for someone else.</p>\n<p>My stereo looks like this:</p>\n<p><img src=\"/content/images/2016/04/toyota-stereo.jpg\" alt=\"\"></p>\n<p>To adjust the time you need to <strong>hold</strong> the 'AM' button and at the same time press the number '1' button to adjust the hour or the number '2' button to adjust the minute.</p>\n<p>I hope this helps someone.</p>\n",
            "url": "https://mrvautin.com/adjust-stereo-clock-on-2006-to-2012-toyota-corolla/",
            "title": "Adjust time on stereo clock for 2006 to 2012 Toyota Corolla",
            "summary": "Adjust time on stereo clock for 2006 to 2012 Toyota Corolla",
            "date_modified": "2013-10-06T10:02:00.000Z"
        },
        {
            "id": "https://mrvautin.com/st-george-bank-woocommerce-plugin-for-ipg-hosted-payment-page--hpp/",
            "content_html": "<p>A St.George Bank IPG Hosted Payment Page (HPP) plugin for WooCommerce. This plugin will allow you to accept payments via your St.George Bank online Merchant Account using your WooCommerce shopping cart</p>\n<p>Download the module <a href=\"http://files.mrvautin.com/stgeorge-woocommerce-1.0.1.zip\">here</a>.</p>\n<p>Here are the steps to install the module:</p>\n<ol>\n<li>Extract the contents of <code>stgeorge-woocommerce-1.0.1.zip</code> to: <code>\\wp-content\\plugins\\</code></li>\n<li>Login to WordPress and install the <code>St.George Bank WooCommerce Plugin</code> via the <code>Plugins</code> Menu</li>\n<li>Go to the <code>WooCommerce &gt; Settings</code> via the left menu</li>\n<li>Click the <code>Checkout</code> tab</li>\n<li>Click on <code>St.George Bank</code> link at the top of the page.</li>\n<li>Click <code>Enable St.George Bank</code> checkbox</li>\n<li>Fill in the desired Title and Description which is shown when the user checks out in WooCommerce</li>\n<li>Copy the <code>Response URL</code> and past this link on the St.George Merchant Administration Console</li>\n<li>Enter the <code>Gateway URL</code> which is obtained via the St.George  Merchant Administration Console &gt; Payment Page Options &gt; URL</li>\n<li>Save the changes and test a payment via your WooCommerce site.</li>\n</ol>\n",
            "url": "https://mrvautin.com/st-george-bank-woocommerce-plugin-for-ipg-hosted-payment-page--hpp/",
            "title": "St George Bank WooCommerce Plugin for IPG Hosted Payment Page (HPP)",
            "summary": "St George Bank WooCommerce Plugin for IPG Hosted Payment Page (HPP)",
            "date_modified": "2013-10-02T04:07:00.000Z"
        },
        {
            "id": "https://mrvautin.com/convert-html-or-a-website-to-an-image-file-c/",
            "content_html": "<p>I was looking around for hours looking for the ability to create an image from some HTML I'd scraped from a Website. Note: This solution also works for Websites which are publicly accessible to don't require authentication.</p>\n<p>It essentially dynamically sets up a WebBrowser control, loads a URL (waits for it to be completely loaded) and takes an image of the rendered HTML. The solution below creates an image which is the full size of the rendered HTML. You can add padding to the image by adding pixels to the <code>wb.Width</code> and <code>wb.Height</code> values.</p>\n<p>It's quite simple really. Here is the function to render the HTML:</p>\n<pre><code class=\"language-c#\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public</span> Bitmap <span class=\"hljs-title\">GenerateScreenshot</span>(<span class=\"hljs-params\"><span class=\"hljs-built_in\">string</span> url</span>)</span>\n    {\n        <span class=\"hljs-comment\">// Load the webpage into a WebBrowser control</span>\n        WebBrowser wb = <span class=\"hljs-keyword\">new</span> WebBrowser();\n        wb.ScrollBarsEnabled = <span class=\"hljs-literal\">false</span>;\n        wb.ScriptErrorsSuppressed = <span class=\"hljs-literal\">true</span>;\n        wb.Navigate(url);\n\n        <span class=\"hljs-comment\">// waits for the page to be completely loaded</span>\n        <span class=\"hljs-keyword\">while</span> (wb.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); }\n\n        <span class=\"hljs-comment\">// Take Screenshot of the web pages full width + some padding</span>\n        wb.Width = wb.Document.Body.ScrollRectangle.Height;\n        <span class=\"hljs-comment\">// Take Screenshot of the web pages full height</span>\n        wb.Height = wb.Document.Body.ScrollRectangle.Height;\n\n        <span class=\"hljs-comment\">// Get a Bitmap representation of the webpage as it&#x27;s rendered in the WebBrowser control</span>\n        Bitmap bitmap = <span class=\"hljs-keyword\">new</span> Bitmap(wb.Width, wb.Height);\n        wb.DrawToBitmap(bitmap, <span class=\"hljs-keyword\">new</span> System.Drawing.Rectangle(<span class=\"hljs-number\">0</span>, <span class=\"hljs-number\">0</span>, wb.Width, wb.Height));\n        wb.Dispose();\n\n        <span class=\"hljs-keyword\">return</span> bitmap;\n    }\n</code></pre>\n<p>You can call it by:</p>\n<pre><code class=\"language-c#\">    Bitmap thumbnail = GenerateScreenshot(<span class=\"hljs-string\">&quot;www.google.com&quot;</span>);\n    thumbnail.Save(<span class=\"hljs-string\">&quot;C:\\image file.bmp&quot;</span>, ImageFormat.Bmp);\n</code></pre>\n<p>Notes:  You can also use <code>C:\\test.html</code> rather than <code>www.google.com</code> and you can change the output file by adjusting the <code>ImageFormat</code> value.</p>\n<p>That's it.</p>\n",
            "url": "https://mrvautin.com/convert-html-or-a-website-to-an-image-file-c/",
            "title": "Convert HTML or a Website to an image file (C#)",
            "summary": "Convert HTML or a Website to an image file (C#)",
            "date_modified": "2013-03-08T09:34:00.000Z"
        }
    ]
}