{ "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/react-native-change-folder-of-app.js-tsx-for-app-to-subfolder/", "content_html": "
You may want to next your app within a different folder to make your dev environment cleaner. You can do this by moving your App.js
or App.tsx
into a /app
folder.
I'm going to move my app into a /app
folder but you may use /src
etc.
Say my structure is currently like this:
\n.expo/\nApp.tsx\nios/\nnode_modules/\n.gitignore\napp.json\npackage.json\n...\n
\nFirst we will create our /app
folder.
We can then move our App.tsx
(App.js
) and the rest of my app /assets
etc to this folder.
Within that folder we will create an AppEntry.tsx
file:
import registerRootComponent from 'expo/build/launch/registerRootComponent';\n\nimport App from './App';\n\nregisterRootComponent(App);\n
\nLastly, we need to tell the app where the entrypoint is. We will need to update our package.json
file by setting the main
:
{\n "name": "my-app",\n "version": "1.0.0",\n "main": "app/AppEntry.tsx",\n "scripts": {\n "start": "expo start",\n "android": "expo run:android",\n "ios": "expo run:ios",\n "web": "expo start --web"\n },\n ...\n}\n
\nYou will end up with a structure like:
\n.expo/\napp/App.tsx\napp/AppEntry.tsx\napp/assets/logo.png\nios/\nnode_modules/\n.gitignore\napp.json\npackage.json\n...\n
\nThat's it, start your app with npm run ios
and away you go. Good luck!
Home Assistant 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.
\nBefore you begin, ensure you have the following:
\nSetting 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!
\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": "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.
\nOne 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.
\nNode.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.
\nNode.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.
\nAs 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.
\nNode.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.
\nNode.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.
\nIn 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.
\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": "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.
\nBefore you begin, you will need the following:
\nTo install Home Assistant, follow these steps:
\npip install homeassistant\n
\nOnce Home Assistant is installed, you need to set it up. Here are the steps:
\nhass\n
\nhttp://localhost:8123
.Once you have set up Home Assistant, you can start adding devices and integrations. Here's how:
\nConfiguration
in the Home Assistant sidebar.Integrations
and then click the +
button.Congratulations! You have successfully installed and set up Home Assistant on your computer.
\nNow 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.
\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": "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.
\nHome 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.
\nHome 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.
\nGetting 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.
\nOnce 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.
\nOne 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.
\nFor 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.
\nIn 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.
\nHome 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.
\nYou 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.
\nHome 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.
\nIf 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.
\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": "\nhelpkb is a superfast and easy to use knowledge base / FAQ to help your customers get the info they need, when they need it most.
\nIt'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 helpkb to do just that. A FREE, super fast and easy to use knowledge base or FAQ so information is always on hand.
\nSo checkout the documentation / demo, and follow our guide to get started building your knowledge base / FAQ today!
\ntaxily allows you to calculate your Australian annual Income, Net pay, Superannuation and Savings with a few simple inputs using the official ATO tax rates.
\n\nOnce you've entered your income and your income cycle you will get a beautiful report showing all the calculated values:
\n\nIn an ideal world, you'd build your Next.js app locally, check it works then deploy the built app to your production server.
\nSometimes you just want to deploy your Next.js 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 PM2 to deploy with no downtime.
\nAn example PM2 ecosystem.config.js
file in the root of your project:
module.exports = {\n apps: [\n {\n name: 'my-app',\n script: 'npm run start',\n cwd: '/Users/mrvautin/Documents/Code/my-app/',\n env: {\n NODE_ENV: 'development'\n },\n env_production: {\n NODE_ENV: 'production'\n }\n }\n ],\n deploy: {\n production: {\n user: 'my-user',\n host: 'my-server',\n key: '/Users/mrvautin/.ssh/id_rsa',\n ssh_options: 'ForwardAgent=yes',\n ref: 'origin/main',\n repo: 'git@github.com:mrvautin/my-app.git',\n path: '/var/www/html/my-app',\n 'post-deploy': 'sh nextjs-pm2-deploy.sh'\n }\n }\n};\n
\nAn example package.json
with our deploy
script:
{\n "name": "my-app",\n "version": "0.1.0",\n "private": true,\n "scripts": {\n "deploy": "pm2 deploy production"\n },\n "dependencies": {},\n "devDependencies": {}\n}\n
\nNow the contents of the nextjs-pm2-deploy.sh
shell script referenced in the post-deploy
section of the ecosystem.config.js
file above:
echo "Deploy starting..."\n\nnpm run install || exit\n\nBUILD_DIR=temp npm run build || exit\n\nif [ ! -d "temp" ]; then\n echo '\\033[31m temp Directory not exists!\\033[0m' \n exit 1;\nfi\n\nrm -rf .next\n\nmv temp .next\n\npm2 reload all --update-env\npm2 reset all\n\necho "Deploy done."\n
\nBasically, this script will install our app, set the build path to /temp
, build the app into /temp
, check the /temp
directory exists then move the contents over and reset our PM2 instance.
All this happens in an instant and should see your app deployed with no noticeable downtime.
\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": "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 a new config panel to setup before writing the image.
Raspberry Pi Imager
hereRaspberry Pi Imager
on your OSRaspberry Pi Imager
CTRL
+SHIFT
+X
\nCMD
+SHIFT
+X
or CTRL
+SHIFT
+X
squido is a dead simple static website builder which can be hosted anywhere for super fast static HTML websites and very little effort.
\nThe advantage of squido 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.
\nStatic websites have many benefits seen here but sometimes it's best to simply try for yourself.
\nSo checkout the documentation, clone one of the demo repos and get started building your website today!
\n\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": "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.
\nSpeed: Static website generally render much faster than a dynamic website due to not having complex rendering, database queries etc.
\nCheap: Static websites can be developed and designed by almost anyone meaning there is reduced costs employing a developer to setup and maintain your website.
\nSimplicity: 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.
\nHosting: There are more hosting options available for a static website, many of which are even free - eg: Github pages or Netlify 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.
\nSimplicity: Simplicity comes at a cost. Static websites lose the ability to do complex processing, database queries etc.
\nLimitations: There are certain things you simply cannot do making static websites suited to certain website types.
\nWhilst 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:
\nThe easiest way to get started is to grab yourself a builder like squido. There is some boiler plate / template examples for a blog or a documentation website to get you started.
\nYou 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 deploy to a hosting provider.
\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": "Managing your environment variable in your different environments can be a pain. The idea behind envz
is that this process is made super simple and easy to understand leading to less mistakes.
# with npm\nnpm install envz\n\n# or with Yarn\nyarn add envz\n
\nRepo: https://github.com/mrvautin/envz
\nYou should use envz
as early on in the entry point of your app as possible. Eg: app.js
or index.js
file which loads your app.
Rather than override process.env.x
object, envz
will return a new object to use throughout your app.
const { envz } = require('envz');\n
\nCreate a env.yaml
or any other named file and load it:
const env = envz('env.yaml');\n
\nThe idea is that the process.env
will be merged with loaded yaml
file.
env
uses a cascading (sequential order) configuration method which is easier to understand looking at an example.
base:\n PORT: 1234\n config:\n default: test\n\ndevelopment:\n PORT: 3000\n DATABASE: dev\n config:\n token: 12345\n secret: fwdsdgl\n\nproduction:\n PORT: 80\n DATABASE: prod\n config:\n token: 67890\n key: puwndklf\n truthy: true\n allowed:\n - card\n - phone\n
\nThe idea here is that the values in base
are loaded, anything in development
overrides that and finally production
overrides that depending on the NODE_ENV
set.
For example, when a NODE_ENV
of development
is set the following env
object is returned:
PORT: 3000,\nconfig: { \n default: 'test', \n token: 12345, \n secret: 'fwdsdgl' \n},\nDATABASE: 'dev'\n...\n
\nEg: Where the PORT
of 3000 from development
overrides the base
setting of 1234. If the NODE_ENV
is set to production
, then the PORT
will be set to 80.
The idea behind base
(or whatever you want to call it) is that you don't need to redefine defaults over and over for each environment.
You can set the environment manually rather than using NODE_ENV
by adding an environment
object. Eg:
const env = envz('env.yaml', { environment: 'production' });\n
\nBy default the values set in process.env
overrides what is set in your yaml file. You can change this so that the yaml file is king by adding the following flag:
const env = envz('env.yaml', { yamlFileOverride: true });\n
\nSometimes you may want to store changes back to your envz
config. You can easily do this by importing save
:
const { save } = require('envz');\n
\nThe save
method takes an object with two values:
envfile
: The yaml file you are wanting to updatedata
: The object you want to update back to the file. See tests and example below.// In this case we will be adding to the `base` config but you can easily\n// replace `base` with `production` or whatever environment.\nconst saveObj = await save({\n envfile: 'test.yaml',\n data: {\n base: {\n config: {\n default: 'default-key'\n }\n }\n }\n});\n
\nThis will result in the test.yaml
being updated:
base:\n PORT: 1234\n config:\n default: default-key\n...\n
\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": "If you are using VS Code its a huge shame if you aren't making use of the amazingly helpful snippets feature.
\nSetting up snippets is easy as:
\nMac
\nCode > Preferences > User Snippets > Select a file or create a new one
Windows
\nFile > Preferences > User Snippets > Select a file or create a new one
Once setup, snippets are triggered by pressing:
\nCTRL+Space
Sometimes its easier to look at an example for the Snippets syntax.
\nA simple console.log
can be sped up using the following syntax. Once triggered the snippet will create a console.log
line and drop your cursor into the middle with single quotes wrapping.
{\n "Console log": {\n "scope": "javascript,typescript",\n "prefix": "log",\n "body": [\n "console.log('$1');"\n ],\n "description": "Log output to console"\n }\n}\n
\nSimple console logging of text:
\n{\n "Console log": {\n "scope": "javascript,typescript",\n "prefix": "log",\n "body": [\n "console.log('$1');"\n ],\n "description": "Log output to console"\n }\n}\n
\nQuick and easy logging of the variable in your clipboard.
\n{\n "Console log variable": {\n\t\t"scope": "javascript,typescript",\n\t\t"prefix": "log var",\n\t\t"body": [\n\t\t\t"console.log('${CLIPBOARD}', ${CLIPBOARD});"\n\t\t],\n\t\t"description": "Console log variable"\n\t}\n}\n
\nQuick for loop
\n{\n "For Loop": {\n "prefix": ["for", "for-const"],\n "body": ["for (const ${2:element} of ${1:array}) {", "\\t$0", "}"],\n "description": "A for loop."\n }\n}\n
\nWrapping code blocks in the markdown code block syntax
\n{\n "Syntax highlighting": {\n "scope": "markdown",\n "prefix": "highlight",\n "body": [\n "``` javascript",\n "${TM_SELECTED_TEXT}",\n "```"\n ],\n "description": "Markdown highlight syntax"\n }\n}\n
\n\n\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": "For more information on variables available see the official snippet docs.
\n
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 WeMos D1 R2 board which can be purchased here.
\n\nThis guide assumes you know your way around Node.Js and have it installed along with NPM.
\nFirstly 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.
\nSelect the board in the Arduino IDE:
\nTools > Board > ESP8266 Boards > WeMos D1 R2
Plugin your board using a USB cable
\nOpen the Wifi firmware:
\nFile > Examples > Firmata > StandardFirmataWifi
You are going to need to setup your Wifi SSID and Passphrase in the WifiConfig.h
file. You shouldn't need to touch the StandardFirmataWifi.h
file at all.
Scroll to the section which has the Wifi SSID configuration and enter the name of your Wifi network (SSID):
\n // replace this with your wireless network SSID\n char ssid[] = "your_network_name";\n
\nScroll to the section which has the Security configuration and enter your passphrase or Wifi password:
\n char wpa_passphrase[] = "your_wpa_passphrase";\n \n
\n
\nThats it. You can now compile and upload the code to your board using the Upload
button
Once that is complete, your board will reset and hopefully connect to your Wifi network.
\nYou 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.
\nNow we are going to setup our Node.Js code to do some simple requests/commands.
\nInstall our dependencies
\nnpm i etherport-client johnny-five --save
Your package.json
should look something like this:
{\n "name": "nodejs-test",\n "version": "1.0.0",\n "description": "",\n "main": "index.js",\n "author": "",\n "license": "ISC",\n "dependencies": {\n "etherport-client": "^0.1.4",\n "johnny-five": "^2.0.0"\n }\n}\n
\nNow to our Node.Js code. We are going to make the little blue light flash which sits next to the silver WeMos
chip on our board:
\n\nYou will need to change the IP address to the one you found in step 9.
\n
\n const { EtherPortClient } = require('etherport-client');\n const { Board, Led } = require('johnny-five');\n \n const board = new Board({\n port: new EtherPortClient({\n host: '192.168.0.201',\n port: 3030\n }),\n repl: false\n });\n \n const LED_PIN = 2;\n \n board.on('ready', () => {\n console.log('Board ready');\n var led = new Led(LED_PIN);\n led.blink();\n });\n
\nNow run your code and check the output in the console and the light action on your board.
\nYou should see some output like this:
\n 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
\nAnd some light action here:
\n
La Marzocco Linea Mini (SVG)
\n\n\nLa Marzocco GS3 (SVG)
\n\nLogos
\n\n\n\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": "Sometimes running Ghost on lower powered server like a Digital Ocean $5 droplet can cause the Ghost CLI to complain about lack of memory: Message: You are recommended to have at least 150 MB of memory available for smooth operation. It looks like you have ~87 MB available.
Adding the --no-mem-check
quickly bypasses this error and gets you on your way.
Command: ghost update --no-mem-check
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!
\nWe 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.
\nEnjoy! Loan calculator
\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": "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.
\nSetup your first DNS in your cluster\n
\nFill in Database as "admin", Username/Password as per the user setup in MongoDB Atlas.
\nSkip SSH tab
\nClick "Use SSL protocol" then select "Self-signed Certificate" from the dropdown.
\nFortunately there are a lot of options for free software to host your shiny new blog. You have definitely heard about Wordpress but is it the best option? Well in my option.. no, it's not.
\nSure Wordpress 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 Ghost is the way to go.
\nGhost 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.
\nBest of all, Ghost is powerful but not vulnerable and requiring updates every 10 minutes for the 50 Wordpress plugins you have installed.
\nSo next time you are looking for some blogging software, give Ghost a go!
\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": "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.
\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": "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.
\nFirstly you will want to create your db.js
file which will export some handy database related functions.
File: db.js
const mongoClient = require('mongodb').MongoClient;\n const mongoDbUrl = 'mongodb://127.0.0.1:27017';\n let mongodb;\n\n function connect(callback){\n mongoClient.connect(mongoDbUrl, (err, db) => {\n mongodb = db;\n callback();\n });\n }\n function get(){\n return mongodb;\n }\n\n function close(){\n mongodb.close();\n }\n\n module.exports = {\n connect,\n get,\n close\n };\n
\nAfter creating this file you can simply require
it and you now have few functions at our disposal. connect
, get
, close
.
File: app.js
You will then want to call connect()
before your application starts and the server starts listening. Eg:
db.connect(() => {\n app.listen(process.env.PORT || 5555, function (){\n console.log(`Listening`);\n });\n });\n
\nNow you have access to your database connection anywhere in your application by simply requiring the db.js
file and using the get()
function.
File: users.js
(routes file for example)
const db = require('./db');\n\nrouter.get('/users', (req, res) => {\n\tdb.get().collection('users').find({}).toArray()\n\t.then((users) => {\n console.log('Users', users);\n });\n});\n
\nIt just makes everything much cleaner and easy to handle this way. I hope this helped you in some way.
\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": "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.
\nYou simply need to run:
\ncat ~/.ssh/id_rsa.pub | ssh root@droplet_ip_address "sudo sshcommand acl-add dokku laptop"
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 \\r
\\r\\n
and <br>
are ignored.
The solution:
\n<br> <br> <br>
No worries, glad I could help!
\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": "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 CNAME
. When the request comes into Heroku the platform will return the "No such application" 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.
Firstly you will want to add your own wildcard custom domain to your Heroku application and also create a CNAME
with your DNS provider.
Adding your CNAME
with your DNS provider to point to Heroku:
Hostname: *.mydomain.com
\nPath: my_heroku_app_name.herokuapp.com
Adding your domain to the Heroku dashboard:
\nDomain Name: *.mydomain.com
\nDNS Target: my_heroku_app_name.herokuapp.com
You will then want to setup your proxy server. I spun up a new Digital Ocean droplet and setup Nginx to proxy the requests.
\nThe Nginx config would look like this:
\nserver {\n listen 80 default_server;\n\n server_name proxy.mydomain.com;\n\n location / {\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $host-customdomain.mydomain.com;\n proxy_redirect off;\n proxy_pass http://my_heroku_app_name.herokuapp.com;\n }\n}\n
\nBasically what is happening is your Nginx server is adding the Host
header and proxing the request onto Heroku. The Heroku router will then read the Host
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.
You will then need to setup an A
DNS record with your DNS provider to point to the new proxy server:
Hostname: proxy.mydomain.com
\nPath: 192.168.0.1 (This IP is your Digital Ocean droplet IP)
You will then want your users of your SaaS application who are wanting a custom domain to point their DNS to proxy.mydomain.com
.
Your Saas application will then need to get the Host
header, remove -customdomain.mydomain.com
and determine who the customer of your SaaS application is.
The SaaS app we built is an FAQ/Knowledge base and support ticketing platform called ezyFAQ - www.ezyfaq.com
\nHaving 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.
\nWe are intending this article to be helpful to anyone wanting to build a SaaS app using Node.Js.
\nUp 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.
\nWe 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.
\nGenerally our database of choice to pair with Node.JS is MongoDB. After trying and considering various other databases, we decided to stick with MongoDB.
\nHosting 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.
\nThis 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.
\nInstead 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.
\nWe 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.
\nWe 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.
\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": "ezyFAQ 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.
\nezyFAQ allows for customising your FAQ/knowledge base with branding, CSS and HTML. ezyFAQ 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!
\nezyFAQ runs its own FAQ using the ezyFAQ platform which you can view here: http://support.ezyfaq.com
\nMore information can be found at www.ezyfaq.com
\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": "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.
\nYou can see the basic structure is really easy to understand. We are exposing the multiply()
function as a public function by returning in the module.exports
. The other function aptly named nonPublic()
is called by the multiply()
function but cannot be called publicly. More on this below.
You can see our multiply()
function takes two values, multiplies them and returns a label from our nonPublic()
function, followed by our multiplied value. Easy!
File: multiply.js
// require any modules\n\nmodule.exports = {\n\tmultiply: function (val1, val2, callback){\n var returnedValue = val1 * val2;\n\t\tcallback(null, nonPublic() + returnedValue);\n\t}\n};\n\nfunction nonPublic(){\n return 'Result: ';\n}\n
\nFile: test.js
Using our new module locally for testing is easy:
\nvar mod = require('./module');\n\nconsole.log(mod.nonPublic());\n\nmod.multiply(5, 10, function(err, result){\n console.log(result);\n});\n
\nThe first line requires our local module. Note: the ./
value for modules located in the same directory.
After we have required it we can go ahead and use it. First we call the nonPublic()
function to show it doesn't work publicly (this outputs an error), then call the multiply()
function.
We pass in 5
and 10
to be multiplied together and we write the result to the console.
To run our test.js
script we simply run the following in our console and observe the output:
node test.js
This is a really basic module which outlines the basic steps to get started on writing your first NPM module.
\nOne of my slightly (hardly) more advanced (has options etc) modules metaget
can be found here as further reading: https://github.com/mrvautin/metaget
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.
\nThe 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.
\nYou 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 app.listen
was my final event.
Here is an example:
\napp.listen(app_port, app_host, function () {\n console.log('App has started');\n app.emit("appStarted");\n});\n
\nThe specific line is:
\napp.emit("appStarted");\n
\nThis creates an event which we can wait on called appStarted
(this can be changed to whatever you want).
Next we need to wait for this event in our Mocha/Supertest tests (test.js
).
First we will require
our Express app. Note: app
is my main Express file, some people use server.js
and this value would then become require('../server')
:
app = require('../app');\n
\nWe then need to create a Supertest agent using our Express instance:
\nvar request = require("supertest");\nvar agent = request.agent(app);\n
\nThen we wait for our Express event using before()
:
before(function (done) {\n app.on("adminMongoStarted", function(){\n done();\n });\n});\n
\nThen we can kick off all our tests. A full test example:
\nvar request = require("supertest");\nvar assert = require('chai').assert;\n\napp = require('../app');\nvar agent = request.agent(app);\n\nbefore(function (done) {\n app.on("appStarted", function(){\n done();\n });\n});\n\ndescribe("Add config",function(){\n it("Add a new connection",function(done){\n agent\n .post("/add_config")\n .expect(200)\n .expect("Config successfully added", done);\n });\n});\n
\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": "markdownTables is an online tool which enables you to paste in your HTML table code and convert it to Markdown table syntax.
\n\n\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": "authorStats
fetches your daily/weekly/monthly download stats for all your authored NPM packages and outputs a nice table right in your command line.
It's best to install the package globally:
\nnpm install author-stats -g
authorStats <npm username>
Where <npm username>
is the username on the NPM website. My profile is: https://www.npmjs.com/~mrvautin
and username is mrvautin
.
A nice command line table with the daily, weekly and monthly download numbers of all your packages will be output to your terminal.
\nNote: If you have a lot of packages you will need to be patient while authorStats
fetches the data.
expressCart is a Shopping Cart built with Nodejs and ExpressJS. The application has PayPal Express Checkout, Stripe checkout and Authorize.Net built-in. expressCart uses MongoDB database backend.
\nThe 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 lunr.js to index the products and enable the best search results.
\nWebsite: https://expresscart.markmoffat.com/
\nDemo: https://expresscart-demo.markmoffat.com
\nHomepage:\n
\nAdmin manage settings:\n
\nPopout cart:\n
\nDashboard:\n
\nUsing PM2 is the easiest and best option for running production websites.\nSee the PM2 for more information or a short guide here: https://mrvautin.com/running-nodejs-applications-in-production-forever-vs-supervisord-vs-pm2/.
\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": "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.
\nThis pushed me to design ghostStrap
which can easily be used as a starting point for anyone wanting to create a theme using the Bootstrap standard.
Some commands may need sudo
cd content/themes/
git clone https://github.com/mrvautin/ghostStrap.git
General
ghostStrap
from the Theme
dropdownPlease leave a comment if you use the theme or have any feedback.
\nHomepage
\n\nSingle post
\n\nMenu
\n\nMobile layout
\n\nMenu
\n\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": "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 blog.
\nFirst 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 www.myblog.com/ghost
, select Labs
from the menu, scroll to the bottom and check the box Public API
.
Now this is turned on, our code will be able to interact with the API to index and search posts.
\nWe are going to use the following Github repository by Windyo here: https://github.com/Windyo/ghostHunter/ this is a Fork of the popular ghostHunter module but has been updated to use the Ghost API, rather than using and hacking RSS feeds. Ghosthunter
uses the extremely powerful Lunr library to index your posts and provide the best, weighted keyword search results.
You will need to download the file jquery.ghostHunter.min.js
from the Github repository and add it to your theme: /content/themes/mytheme/assets/js/
.
You will then need to add a reference to that file in: /content/themes/mytheme/default.hbs
{% raw %}\n <script type="text/javascript" src="{{asset "js/jquery.ghostHunter.min.js"}}"></script>\n {% endraw %}\n
\nNote: Add it at the bottom of the file after the jQuery reference
\nOnce you have done that you can start adding the search box to your page(s).
\nYou 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 /content/themes/mytheme/assets/js/index.js
file.
There are various options on the Ghosthunter module. I've decided to display results as they are typed and have set the onKeyUp
to true
and have chosen to hide the number of results by setting displaySearchInfo
to false. Check the Github repository for more options.
$(".search-results").addClass("results-hide");\n$("#search-field").ghostHunter({\n results: "#search-results",\n onKeyUp: true,\n displaySearchInfo: false,\n result_template : "<a href='{{link}}'><li class='list-group-item'>{{title}}</li></a>",\n before: function(){ \n $(".search-results").removeClass("results-hide");\n }\n}); \n
\nNote: My theme is using Twitter Bootstrap so you will see references to list-group-item
etc which you can remove and add your own CSS styling.
Next thing you need to do is add some simple CSS to your /content/themes/mytheme/assets/js/screen.css
to format the search and results box.
.search-box{\n margin-bottom: 10px;\n}\n\n.search-results {\n position:absolute;\n z-index: 1000;\n}\n\n.search-button{\n background-color: #1B95E0;\n color: white;\n}\n\n.results-hide{\n display: none;\n}\n
\nNote: You can edit styling as you wish.
\nLastly you will need to add the search box to your template file: /content/themes/mytheme/index.hbs
. You can also add this to your post.hbs
view too if you wish.
<div class="row">\n <div class="search-box col-xs-12 col-sm-12 col-md-4 col-md-offset-4 col-lg-4 col-lg-offset-4">\n <div class="input-group">\n <input type="text" id="search-field" class="form-control input-lg" placeholder="Search for...">\n <span class="input-group-btn">\n <button class="btn btn-default search-button btn-lg" type="button">Search!</button>\n </span> \n </div>\n </div>\n</div>\n<section class="search-results col-xs-12 col-sm-12 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2" > \n <ul id="search-results" class="search-results col-md-12" class="list-group"></ul>\n</section>\n
\nPlease let me know in the comments what you think.
\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": "If you are wanting to setup your Ghost blog URL to be HTTPS
(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.
The production section of your Ghost config.js
will look something like this:
production: {\n\turl: 'https://mrvautin.com',\n\tmail: {},\n\tdatabase: {}\n}\n\n
\nDepending on your web server the setting is slightly different. We are going to cover off Apache
and Nginx
as they are most popular.
A simple Nginx
config would look like:
server {\n\tlisten 443 ssl;\n\tserver_name mrvautin.com www.mrvautin.com;\n\t# SSL STUFF\n\n\tlocation / {\n\t\tproxy_set_header X-Real-IP $remote_addr;\n\t\tproxy_set_header Host $http_host;\n\t\tproxy_pass http://127.0.0.1:2368;\n\t\tproxy_set_header X-Forwarded-Proto $scheme;\n\t}\n}\n
\nThe important line above is:
\nproxy_set_header X-Forwarded-Proto $scheme;
This line ensures the Header which Ghost reads has the correct protocol set.
\nA simple Apache
virtual host config would look like:
<VirtualHost *:443>\n RequestHeader set X-Forwarded-Proto "https"\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 <Location/>\n SSLRequireSSL\n </Location>\n\n ProxyPass / http://127.0.0.1:2368\n ProxyPassReverse / http://127.0.0.1:2368\n</VirtualHost>\n
\nThe important line above is:
\nRequestHeader set X-Forwarded-Proto "https"
This line ensures the Header which Ghost reads has the correct protocol set.
\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": "The Casper theme by default has an excerpt with all HTML tags / formatting removed. You can change this in your theme by editing the /content/themes/mytheme/partials/loop.hbs
file of your theme.
In the loop.hbs
file you will see:
{% raw %}\n{{excerpt words="26"}}\n{% endraw %}\n
\nYou will need to change the word excerpt
to content
. The new code will be:
{% raw %}\n{{content words="26"}}\n{% endraw %}\n
\nIf you are wanting to change the length (amount of words) of the excerpt please see here.
\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": "Changing the post excerpt length (teaser text) of your theme is relatively simple. You will need to edit the /content/themes/mytheme/partials/loop.hbs
When opening your loop.hbs
file you will see code like the this:
You can change the default Casper value of 26 to any value you want:
\nYou can play around and change this value and see what length best suits your writing style and theme.
\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": "A Node.js module to fetch HTML meta tags (including Open Graph) from a remote URL
\nnpm install metaget --save
var metaget = require("metaget");\nmetaget.fetch('https://wordpress.com', function (err, meta_response) {\n\tif(err){\n\t\tconsole.log(err);\n\t}else{\n\t\tconsole.log(meta_response);\n\t}\n});\n
\nResponse 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:
\nmeta_response["og:title"];\n
\nIt'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 "request".
\nThis is how you would specify a "User-Agent" of a Google Bot:
\nvar metaget = require("metaget");\nmetaget.fetch('https://wordpress.com',{headers:{"User-Agent": "Googlebot"}}, function (err, meta_response) {\n\tif(err){\n\t\tconsole.log(err);\n\t}else{\n\t\tconsole.log(meta_response);\n\t}\n});\n
\ngit checkout -b my-new-feature
git commit -am 'Add some feature'
git push origin my-new-feature
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.
\n\n\nadminMongo 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.
\n
git clone https://github.com/mrvautin/adminMongo.git && cd adminMongo
npm install
npm start
adminMongo will listen on host: localhost
and port: 1234
by default.\nThis can be overwritten by adding a config file in /config/app.json
. The config file can also override the default 5 docs per page.\nThe config file options are:
{\n "app": {\n "host": "10.0.0.1",\n "port": 4321,\n "docs_per_page": 15\n }\n}\n
\nAfter visiting http://127.0.0.1:1234 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: mongodb://<user>:<password>@127.0.0.1:<port>/<db>
where specifying to the <db>
level is optional. For more information on MongoDB connection strings, see the official MongoDB documentation.
Note: The connection can be either local or remote hosted on VPS or MongoDB service such as MongoLab.
\nAfter 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.
\nAfter selecting your collection from the "Database Objects" 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.
\nYou can search documents using the Search documents
button on the collections screen. You will need to enter the key (field name) and value. Eg: key = "_id" and value = "569ff81e0077663d78a114ce".
\n\nYou can clear your search by clicking the
\nReset
button on the collections screen.
Adding and editing documents is done using a JSON syntax highlighting control.
\nIndexes can be added from the collection screen. Please see the official MongoDB documentation on adding indexes.
\ngit checkout -b my-new-feature
git commit -am 'Add some feature'
git push origin my-new-feature
Common App Bundle ID list (case sensitive)
\nThese are used in your mytheme.theme/Bundles folder.
\nApp Name | \nBundle ID | \n
---|---|
1Password | \ncom.agilebits.onepassword-ios | \n
500px | \ncom.500px | \n
9gag | \ncom.9gag.ios.mobile | \n
Activator | \nlibactivator | \n
Airbnb | \ncom.airbnb.app | \n
Amazon | \ncom.amazon.Amazon | \n
App Store | \ncom.apple.AppStore | \n
Ask Fm | \nfm.ask.askfm | \n
BiteSMS | \ncom.bitesms | \n
Calculator | \ncom.apple.calculator | \n
Calendar | \ncom.apple.mobilecal | \n
Camera + | \ncom.taptaptap.cloudphotos | \n
Camera | \ncom.apple.camera | \n
Chase Mobile | \ncom.chase | \n
Circle the Dot | \ncom.ketchapp.circlethedot | \n
Clock | \ncom.apple.mobiletimer | \n
CNN | \ncom.cnn.iphone | \n
Compass | \ncom.apple.compass | \n
Contacts | \ncom.apple.MobileAddressBook | \n
Digg | \ncom.digg.Digg | \n
Dropbox | \ncom.getdropbox.Dropbox | \n
Ebay | \ncom.ebay.iphone | \n
Edline | \ncom.alecgorge.Brebeuf-Edline | \n
Engadget | \ncom.aol.engadget | \n
ESPN SportsCenter | \ncom.espn.ScoreCenter | \n
eTrade | \ncom.etrade.mobileproiphone | \n
ETSY | \ncom.etsy.etsyforios | \n
Evernote | \ncom.evernote.Evernote | \n
Evernote | \ncom.evernote.iPhone.Evernote | \n
Facebook Groups | \ncom.facebook.Groups | \n
Facebook Page Admin | \ncom.facebook.PageAdminApp | \n
Facebook Paper | \ncom.facebook.Paper | \n
com.facebook.Facebook | \n|
Facetime | \ncom.apple.facetime | \n
FB Messenger | \ncom.facebook.Messenger | \n
Find my iPhone | \ncom.apple.mobileme.fmip1 | \n
Firefox | \norg.mozilla.ios.Firefox | \n
Flappy Bird | \ncom.dotgears.flap | \n
Fleksy | \ncom.syntellia.Fleksy | \n
Foap | \ncom.foap.foap | \n
Game Center | \ncom.apple.gamecenter | \n
Gamestop | \ncom.gamestop.powerup | \n
Google + | \ncom.google.GooglePlus | \n
Google Chrome | \ncom.google.chrome.ios | \n
Google Chromecast | \ncom.google.Chromecast | \n
Google Docs | \ncom.google.Docs | \n
Google Drive | \ncom.google.Drive | \n
Google Gmail | \ncom.google.Gmail | \n
Google Inbox | \ncom.google.inbox | \n
Google Maps | \ncom.google.Maps | \n
Google Photos | \ncom.google.photos | \n
Google Search | \ncom.google.GoogleMobile | \n
Google Translate | \ncom.google.Translate | \n
Health | \ncom.apple.Health | \n
iBooks | \ncom.apple.iBooks | \n
iFile | \neu.heinelt.ifile | \n
iMessage | \ncom.apple.MobileSMS | \n
iMovie | \ncom.apple.iMovie | \n
com.burbn.instagram | \n|
iTunes Connect | \ncom.apple.itunesconnect.mobile | \n
iTunes Store | \ncom.apple.MobileStore | \n
Kickstarter | \ncom.kickstarter.kickstarter | \n
com.linkedin.LinkedIn | \n|
com.apple.mobilemail | \n|
Make it Rain | \ncom.SpaceInch.LoveOfMoney | \n
Maps | \ncom.apple.Maps | \n
Medium | \ncom.medium.reader | \n
ModMyi | \ncom.modmyi.ModMyi | \n
Music | \ncom.apple.Music | \n
Myspace | \ncom.myspace.iPhone | \n
Netflix | \ncom.netflix.Netflix | \n
Notes | \ncom.apple.mobilenotes | \n
Ookla Speedtest | \ncom.ookla.speedtest | \n
Oovoo | \ncom.oovoo.iphone.free | \n
Outlook | \ncom.microsoft.Office.Outlook | \n
outube | \ncom.youtube.ios.youtube | \n
Pandora | \ncom.pandora.pandora | \n
Passbook | \ncom.apple.Passbook | \n
Paypal | \ncom.yourcompany.PPClient | \n
Phonto | \ncom.youthhr.Phonto Y | \n
PhotoMath | \ncom.microblink.PhotoMath Xbox | \n
Photos | \ncom.apple.mobileslideshow | \n
Photoshop Express | \ncom.adobe.PSMobile | \n
Piano Tiles | \ncom.umonistudio.tapTile | \n
Podcasts | \ncom.apple.podcasts | \n
Quizup | \ncom.plainvanillacorp.quizup | \n
com.tyanya.reddit | \n|
Reeder | \nch.reeder | \n
Release Slow Shutter | \ncom.cogitap.SlowShutter | \n
Reminders | \ncom.apple.reminders | \n
Remote Mouse | \ncom.remotemouse.remoteMouse | \n
Remote | \ncom.apple.Remote | \n
Safari | \ncom.apple.mobilesafari | \n
Settings | \ncom.apple.Preferences | \n
Skype | \ncom.skype.skype | \n
Smartglass | \ncom.microsoft.xboxavatars | \n
Snapchat | \ncom.toyopagroup.picaboo | \n
SoundHound | \ncom.melodis.midomi | \n
Spotify | \ncom.spotify.client | \n
Square Cash | \ncom.squareup.cash | \n
Stay in the Line | \ncom.six8t.StayInTheLine | \n
Stocks | \ncom.apple.stocks | \n
Stop Motion | \ncom.cateater.funapps.stopmotion | \n
Swing Copters | \ncom.dotgears.swing | \n
Teamviewer | \ncom.teamviewer.teamviewer | \n
Terminal | \ncom.googlecode.mobileterminal.Terminal | \n
Testflight | \ncom.apple.TestFlight | \n
Things | \ncom.culturedcode.ThingsTouch | \n
Tinder | \ncom.cardify.tinder | \n
Tips | \ncom.apple.tips | \n
Tumblr | \ncom.tumblr.tumblr1Password | \n
Tweetbot 3 | \ncom.tapbots.Tweetbot3 | \n
Tweetbot 4 | \ncom.tapbots.Tweetbot4 | \n
Tweetbot iPad | \ncom.tapbots.TweetbotPad | \n
Tweetbot | \ncom.tapbots.Tweetbot | \n
com.atebits.Tweetie2 | \n|
Ultimate Guitar Tabs | \ncom.ultimateguitar.tabs100 | \n
Viber | \ncom.viber | \n
Videos | \ncom.apple.videos | \n
Vidgets | \ncom.lesscode.widgetcenter | \n
Vimeo | \ncom.vimeo | \n
Voice Memos | \ncom.apple.VoiceMemos | \n
Weather | \ncom.apple.weather | \n
net.whatsapp.WhatsApp | \n|
Winterboard | \ncom.saurik.Winterboard | \n
WWDC | \ndeveloper.apple.wwdc | \n
WWDC | \ndeveloper.apple.wwdc-Release | \n
Yahoo Weather | \ncom.yahoo.weather | \n
YouTube | \ncom.google.ios.youtube | \n
Common icon names and sizes (px):
\nIcon name | \nSize | \n
---|---|
AppIcon76x76~ipad.png | \n76x76 | \n
AppIcon29x29@2x.png | \n58x58 | \n
AppIcon40x40@2x.png | \n80x80 | \n
AppIcon60x60@2x.png | \n120x120 | \n
AppIcon76x76@2x~ipad.png | \n152x152 | \n
AppIcon29x29@3x.png | \n87x87 | \n
AppIcon40x40@3x.png | \n120x120 | \n
AppIcon60x60@3x.png | \n180x180 | \n
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 "NBA Lockscreen scores" 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.
\n[Cydia link](cydia://search/nba lockscreen scores)
\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": "You may experience an issue where older notes are considered "ON MY IPHONE" 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.
\nNOTE: The app may not update the number of notes until it's closed and reopened.
\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": "openKB is an open source Markdown based Knowledge base application (FAQ) built with Nodejs and ExpressJS. The application uses an embedded database (nedb) 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.
\nDemo: http://openkb.mrvautin.com
\ngit clone https://github.com/mrvautin/openKB.git && cd openKB
npm install
npm start
/public/stylesheets/
and adding a link in /views/layouts/layout.hbs
you can add your own styling and graphics.admin
can be a little difficult editing Markdown on smaller screens.\n\n\n\n
\nVisit: http://127.0.0.1:4444/login
\nA new user form will be shown where a user can be created.
\nThere are are a few configurations that can be made which are held in /routes/config.js
. If any values have been changed the app will need to be restarted.
Using PM2 seems to be the easiest and best option for running production websites.\nSee the PM2 for more information or a short guide here: http://mrvautin.com/Running-Nodejs-applications-in-production-forever-vs-supervisord-vs-pm2.
\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": "There are a few aspects to think of when setting up a Nodejs application in production. I'm going to cover off Process management
and Webservers
.
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 WILL come back online automatically. With Nodejs, if the process crashes or the server restarts the process will NOT start itself. This is where a process manager comes into play, luckily there are a few good ones to choose from.
\nI will run through some of them and detail their pros and cons but to summarise: I like PM2 for easy setup of personal projects but I definitely recommend setting up systemd for a proper production environment.
\nPros
\nCons
\nPros
\nCons
\nPros
\npm2 list
give an easy to read table of all appsCons
\nPros
\nCons
\nI'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.
\nHere is a short guide on setting up Nginx for your Nodejs app:
\nFirstly need to install Nginx. Eg: Ubuntu: $ sudo apt-get install nginx
You the want to create the config for your application
\n$ sudo nano /etc/nginx/sites-available/myapp
The following is a very basic config to run your application. Basically it will listen for requests to mydomain.com
on HTTP and forward those requests to our app (running with a process manager above) on port 4444
. You will need to change that port to whatever port your app is running/listening on.
server {\n listen 80;\n server_name mydomain.com;\n\n location / {\n proxy_pass http://localhost:4444;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection 'upgrade';\n proxy_set_header Host $host;\n proxy_cache_bypass $http_upgrade;\n }\n}\n
\nYou can then save this file and test your Nginx config with:
\n$ nginx -t
All going well, you should get something like this:
\nnginx: the configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf test is successful\n
\nIf not, check the error and adjust your config to resolve.
\nAfter 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.
\nReload: $ service nginx reload
Restart: $ service nginx restart
Thats it! You should be able to visit your app at: http:mydomain.com
\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": "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.
\nSome of the Meta tags you will want to set are called Open Graph 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.
\nAll Metadata should be found within the <head>
tag of your HTML document. The basic code of a Metadata is:
<meta property="property_value" content="content_value"/>\n
\nWhere property_value
is the actual Metadata we want to set and content_value
is the actual value you would like.
A list of Open Graph properties can be found here: http://ogp.me/
\nThe main ones you want to concentrate on are:
\nThe 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.
\nExample:
\n<meta property="og:url" content="http://mrvautin.com/Adding-Facebook-Open-Graph-Metadata-to-your-website"/>\n
\nThe title, headline or name of the object/article. This is shown when the URL/object is embedded into Facebook.
\nExample:
\n<meta property="og:title" content="Adding Facebook Open Graph Metadata to your website"/>\n
\nA two sentence description/summary of the article/URL.
\nExample:
\n<meta property="og:description" content="A short two sentence description of the article."/>\n
\nHere 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.
\nExample:
\n<meta property="og:image" content="http://mrvautin.com/path_to_image.png"/>\n
\nThis is the type of URL being shared. Facebook outlines a long list of og:type options but for a general website/blog you will want to use article
.
Example:
\n<meta property="og:type" content="article" />\n
\n<html>\n<head>\n<meta property="og:url" content="http://mrvautin.com/Adding-Facebook-Open-Graph-Metadata-to-your-website"/>\n<meta property="og:title" content="Adding Facebook Open Graph Metadata to your website"/>\n<meta property="og:description" content="Adding Facebook Open Graph Metadata to your website"/>\n<meta property="og:image" content="http://mrvautin.com/path_to_image.png"/>\n<meta property="og:type" content="article" />\n</head>\n<body>\n Content\n</body>\n</html>\n
\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": "A light weight blogging platform built on Node.js and Express. The antlers 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!
\nantlers allows for easy templating (themes) using the Handlebars templating engine and includes a few themes out of the box.
\nTo get an idea of how your blog will look, take a look around! This blog is powered by antlers.
\nUsing: npm
\nor
\nManual:
\nnpm install
as an administrator (eg: sudo might be required)node app.js
You can enter the admin panel of your newly created blog by visiting the following URL in your browser: http://localhost:3333/admin. The default user login is: test@test.com and password is: password1. After logging in, you can change the email (username) and password using the "Users" menu.
\nMediatomb is apparently pre-installed.. It doesn't seem to be on my NAS.
\nThe easiest way to install Mediatomb is via Optware.
\nTo install Optware you simply need to run:
\n# 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
\nYou can then install Mediatomb by running:
\n# /opt/bin/ipkg install mediatomb\n
\nThen copy the Mediatomb startup script to "start":
\n# cp /opt/etc/init.d/mediatomb /ffp/start/mediatomb.sh\n
\nThen set the correct permissions on the "mediatomb.sh file:
\n# chmod a+x /ffp/start/mediatomb.sh\n
\nYou need to change one of the Mediatomb configs to allow autostart:
\n# vi /opt/etc/default/mediatomb\n
\nEnsure MT_ENABLE=true
\nYou can now start Mediatomb by:
\n# sh /ffp/start/mediatomb.sh start\n
\nYou can now browse Mediatomb via the Web Interface:
\nhttp://localhost:4915\n
\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": "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.
\nMy stereo looks like this:
\n\nTo adjust the time you need to hold 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.
\nI hope this helps someone.
\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": "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
\nDownload the module here.
\nHere are the steps to install the module:
\nstgeorge-woocommerce-1.0.1.zip
to: \\wp-content\\plugins\\
St.George Bank WooCommerce Plugin
via the Plugins
MenuWooCommerce > Settings
via the left menuCheckout
tabSt.George Bank
link at the top of the page.Enable St.George Bank
checkboxResponse URL
and past this link on the St.George Merchant Administration ConsoleGateway URL
which is obtained via the St.George Merchant Administration Console > Payment Page Options > URLI 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.
\nIt 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 wb.Width
and wb.Height
values.
It's quite simple really. Here is the function to render the HTML:
\n public Bitmap GenerateScreenshot(string url)\n {\n // Load the webpage into a WebBrowser control\n WebBrowser wb = new WebBrowser();\n wb.ScrollBarsEnabled = false;\n wb.ScriptErrorsSuppressed = true;\n wb.Navigate(url);\n\n // waits for the page to be completely loaded\n while (wb.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); }\n\n // Take Screenshot of the web pages full width + some padding\n wb.Width = wb.Document.Body.ScrollRectangle.Height;\n // Take Screenshot of the web pages full height\n wb.Height = wb.Document.Body.ScrollRectangle.Height;\n\n // Get a Bitmap representation of the webpage as it's rendered in the WebBrowser control\n Bitmap bitmap = new Bitmap(wb.Width, wb.Height);\n wb.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, wb.Width, wb.Height));\n wb.Dispose();\n\n return bitmap;\n }\n
\nYou can call it by:
\n Bitmap thumbnail = GenerateScreenshot("www.google.com");\n thumbnail.Save("C:\\image file.bmp", ImageFormat.Bmp);\n
\nNotes: You can also use C:\\test.html
rather than www.google.com
and you can change the output file by adjusting the ImageFormat
value.
That's it.
\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" } ] }