<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Webmaster-Source &#187; Featured</title>
	<atom:link href="https://www.webmaster-source.com/category/featured/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.webmaster-source.com</link>
	<description>Useful Resources For Webmasters</description>
	<lastBuildDate>Thu, 24 Aug 2017 02:01:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Installing Multiple Ghost Blogs Behind NGINX on Ubuntu 12.04</title>
		<link>https://www.webmaster-source.com/2013/11/06/installing-multiple-ghost-blogs-behind-nginx-on-ubuntu-12-04/</link>
		<comments>https://www.webmaster-source.com/2013/11/06/installing-multiple-ghost-blogs-behind-nginx-on-ubuntu-12-04/#comments</comments>
		<pubDate>Wed, 06 Nov 2013 15:15:16 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Software & Scripts]]></category>
		<category><![CDATA[DigitalOcean]]></category>
		<category><![CDATA[Ghost]]></category>
		<category><![CDATA[Hosting]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5236</guid>
		<description><![CDATA[Looking to set up a blog with Ghost? While it still has a few rough edges and missing features at the time of this writing, as it&#8217;s essentially in beta at this point (hence the &#8220;0.3&#8221; versioning), it definitely shows promise as a blogging platform. If you&#8217;re reading this, you&#8217;re probably aware that you can&#8217;t [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="//www.webmaster-source.com/wp-content/uploads/2013/10/ghost-logo.png" alt="Ghost Logo" width="196" height="135" class="alignright size-full wp-image-5201 imgborder" />Looking to set up a blog with <a href="http://ghost.org">Ghost?</a> While it still has a few rough edges and missing features at the time of this writing, as it&#8217;s essentially in beta at this point (hence the &#8220;0.3&#8221; versioning), it definitely <a href="http://www.webmaster-source.com/2013/10/02/ghost-the-new-blogging-platform-and-why-it-matters/">shows promise</a> as a blogging platform.</p>
<p>If you&#8217;re reading this, you&#8217;re <em>probably</em> aware that you can&#8217;t just FTP Ghost to a dinky shared host and expect it to run like your average PHP script. Ghost is a Node.js application, which works differently, and has yet to be adopted by services that generally cater to newbies. You&#8217;re going to need a <abbr title="Virtual Private Server">VPS</abbr> and command line access. I&#8217;m also going to assume a rudimentary knowledge of Linux commands. (You can pick up the basics pretty easily at <a href="http://linuxcommand.org/">linuxcommand.org</a> if need be.)</p>
<p>This tutorial aims to walk you through the process of installing one ore more instances of Ghost behind the NGINX server. NGINX is a fast and lightweight web server that, when configured in this manner, acts as a proxy, forwarding requests to the correct Ghost blog.</p>
<h3>DigitalOcean</h3>
<p>I&#8217;m a big fan of <a href="https://www.digitalocean.com/?refcode=b6711983671a">DigitalOcean</a>. I&#8217;ve been hosting my various web sites with them since this June, and their service has been of excellent quality. In addition to their rock-bottom price, their virtual machines have performed well and their staff has been competent and helpful. (You can find my review of DigitalOcean here.)</p>
<p>$5/month will get you a &#8220;Droplet&#8221; with 512MB of RAM, 20GB of storage on a solid state drive and plenty of data transfer. (It&#8217;s a soft cap with reasonable overages. You&#8217;re very, very unlikely to ever reach it, though. Unless you&#8217;re a popular podcaster or something, in which case you should be looking into a CDN&#8230;)</p>
<p>The figure that&#8217;s the most important is the RAM. Just like with the computer you&#8217;re using to read this, active applications reside in the system&#8217;s memory, and the amount they use varies depending on what the app is doing. Ghost, in my informal tests, doesn&#8217;t seem to be too memory-intense. So a 512MB Droplet could probably host a few Ghost blogs at once, depending on their popularity and how the system is configured.</p>
<p>There are plenty of options for a VPS, though. If you&#8217;re not too keen on DigitalOcean, <a href="https://www.linode.com/">Linode</a>, <a href="http://www.rackspace.com/">Rackspace</a>, <a href="http://aws.amazon.com/ec2/">Amazon EC2</a> and <a href="http://ramnode.com/">RamNode</a> are popular. If you want to give DigitalOcean a try, you can sign up with the promo code DIVEIN5 to get a $5 credit. You can also pay by the hour if you just want to fire up a VM for a few hours to experiment before making a decision.</p>
<h3>Initial Setup</h3>
<p>Once you&#8217;ve got your VPS, it&#8217;s time to start setting things up. For simplicity, I will assume you are running Ubuntu 12.04. You can follow along with any Linux distribution on any hosting provider, but some commands may be a little different.</p>
<p>First, if you haven&#8217;t already, use SSH to log in to your <abbr title="Virtual Machine">VM</abbr> as <code>root</code>, using the password your host gave you. Take this opportunity to change your password to something different, and reasonably strong, for security. Just run the <code>passwd</code> command and follow the on-screen instructions.</p>
<p>Now let the system update its package index by running the following command:</p>
<pre class="brush: bash; title: ; notranslate">apt-get update</pre>
<p>While you&#8217;re at it, install the <code>unzip</code> tool so you can unpack the Ghost archive later on.</p>
<pre class="brush: bash; title: ; notranslate">apt-get install unzip</pre>
<p><span id="more-5236"></span></p>
<h3>Installing Node.js</h3>
<p>Now we need to install <a href="http://nodejs.org/">Node.js</a>, the JavaScript platform that Ghost is built on. Ubuntu&#8217;s pre-made package probably isn&#8217;t new enough to run Ghost, so we&#8217;ll have to compile it ourselves.</p>
<p>First, install the Linux build tools through Ubuntu&#8217;s package manager. This will install the necessary compilers, as well as the <code>make</code> tool.</p>
<pre class="brush: bash; title: ; notranslate">apt-get install build-essential</pre>
<p>Now you need to change to your home folder, make a new directory to contain the source, and download Node.js.</p>
<pre class="brush: bash; title: ; notranslate">
cd
mkdir src
cd src
wget http://nodejs.org/dist/v0.10.21/node-v0.10.21.tar.gz
</pre>
<p>If you run <code>ls</code>, you should see the archive in the src directory. If the file was successfully downloaded, you can unpack the archive and change to the resulting directory.</p>
<pre class="brush: bash; title: ; notranslate">
tar -zxvf node-v0.10.21.tar.gz
cd node-v0.10.21
</pre>
<p>Ready to compile? After you run the next two commands, be prepared to wait 5-10 minutes while the system works its magic and converts raw source code into an executable binary.</p>
<pre class="brush: bash; title: ; notranslate">
./configure
make
</pre>
<p>Once the messages stop scrolling by and the command prompt returns, you just need to run the installer.</p>
<pre class="brush: bash; title: ; notranslate">
make install
</pre>
<p>Congratulations, you&#8217;ve successfully compiled and installed a program from source! To verify that everything worked properly, run <code>node -v</code>. It should output the Node.js version, which in this case is v0.10.21. (Or a greater version if there is a newer one out by the time you read this.)</p>
<h3>Ghost Installation</h3>
<p>The next step is to install a copy of Ghost for each of your blogs. First, let&#8217;s make a place for them to reside in.</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /var/ghost
cd /var/ghost
</pre>
<p>If you intend to use an FTP client to make it easier to upload themes or such, /var/ghost is the place where your blogs&#8217; files will be found. So it&#8217;s a good path to remember. (On a related note, the SSH process also doubles as a secure FTP server. If your FTP client supports SFTP, you can connect to the domain/IP and log in with a valid username and password.)</p>
<p>To add a copy of Ghost, just follow these steps:</p>
<pre class="brush: bash; title: ; notranslate">
mkdir myghostblog
cd myghostblog
wget https://ghost.org/zip/ghost-0.3.3.zip
unzip ghost-0.3.3.zip
rm ghost-0.3.3.zip
npm install --production
</pre>
<p>What you&#8217;re doing is:</p>
<ol>
<li>Creating a folder for the blog</li>
<li>Changing to that folder</li>
<li>Downloading Ghost</li>
<li>Unzipping Ghost</li>
<li>Removing the .zip file</li>
<li>Installing Ghost</li>
</ol>
<p>Before we can actually start Ghost up, there is some essential configuration that needs to be adjusted.</p>
<p>Copy the example configuration file to a new <code>config.js</code> file with <code>cp config.example.js config.js</code>. Open the <code>config.js</code> file in the <code>nano</code> text editor with <code>nano config.js</code>. Use the arrow keys to scroll down to where the &#8220;production&#8221; environment starts in the config. It looks something like this:</p>
<pre class="brush: jscript; title: ; notranslate">
production: {
    url: 'http://my-ghost-blog.com',
    mail: {},
    database: {
        client: 'sqlite3',
        connection: {
            filename: path.join(__dirname, '/content/data/ghost.db')
        },
        debug: false
    },
    server: {
        host: '127.0.0.1',
        port: '2368'
    }
},
</pre>
<p>There are three things you need to change:</p>
<ol>
<li>The <code>url</code> field. Replace <code>http://my-ghost-blog.com</code> with <code>http://whatever-your-domain-is.com</code>.</li>
<li>The <code>port</code> field in the <code>server</code> block may need to be changed, depending on whether this is the first blog you&#8217;re setting up or not.</li>
</ol>
<p>To save the file, press control+o and, then control+x to exit.</p>
<p>Web browsers, by default, connect to HTTP port 80 when requesting a web page. The way we&#8217;re setting this up, NGINX will listen on port 80, waiting for requests, and forward them to the ports your Ghost blogs are listening on. So Blog A can listen on port 2368 and Blog B can listen on port 2369. NGINX will listen on port 80, figure out which domain name belongs to which blog, and route the requests to the appropriate port.</p>
<p>Repeat the relevant steps in this section to set up additional blogs. You can wait until after you&#8217;ve finished setting up the first, if you want.</p>
<h3>Upstart</h3>
<p>We need to make it easy to start and stop the Ghost processes, and ensure that they come back online automatically if the server is restarted. On Ubuntu, it&#8217;s super simple with a system known as Upstart.</p>
<p>First, create a new Upstart configuration file called <code>ghost.conf</code>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/init
nano ghost.conf
</pre>
<p>Now fill it with the following Upstart script, replacing <code>myghostblog</code> with the directory you created for your blog:</p>
<pre class="brush: plain; title: ; notranslate">
start on startup

script
    cd /var/ghost/myghostblog
    npm start --production
end script
</pre>
<p>If you have multiple Ghost blogs set up, you would do something like this:</p>
<pre class="brush: plain; title: ; notranslate">
start on startup

script
    cd /var/ghost/myghostblog
    npm start --production
    cd /var/ghost/myotherghostblog
    npm start --production
end script
</pre>
<h3>NGINX Installation</h3>
<pre class="brush: bash; title: ; notranslate">
apt-get install nginx
</pre>
<p>That was easy, wasn&#8217;t it?</p>
<h3>NGINX Configuration</h3>
<p>NGINX keeps its site configuration files in two directories within <code>/etc/nginx</code>:</p>
<ul>
<li><code>sites-available</code> — Each site gets its own configuration file in here</li>
<li><code>sites-enabled</code> — This directory contains <a href="http://en.wikipedia.org/wiki/Symbolic_link">symbolic links</a> pointing to the files in <code>sites-available</code>.</li>
</ul>
<p>Let&#8217;s create a new site configuration for <code>myghostblog</code>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/nginx/sites-available
nano myghostblog
</pre>
<p>A simple configuration that does nothing but pass traffic addressed to <code>my-awesome-ghost-blog.com</code> to the Ghost blog listening on port 2368 looks like this:</p>
<pre class="brush: plain; title: ; notranslate">
server {
    server_name my-awesome-ghost-blog.com;

    location / {
        proxy_pass http://127.0.0.1:2368;
    }
}
</pre>
<p>Of course, <a href="http://wiki.nginx.org/Main">NGINX</a> is a powerful and flexible piece of software that is capable of a lot more. This is just one of many things you can use it for.</p>
<p>As before, save the file by pressing control+o and quit nano with control+x. Next, move back up one directory level to /etc/nginx and create a symbolic link in <code>sites-enabled</code>, pointing to the file in <code>sites-available</code>.</p>
<pre class="brush: bash; title: ; notranslate">
cd ../
ln -s sites-available/myghostblog sites-enabled/myghostblog
</pre>
<h3>Fire it Up</h3>
<p>Now that you have everything configured, you can start (or stop) the processes with the <code>service</code> command.</p>
<pre class="brush: bash; title: ; notranslate">
service ghost start
service nginx start
</pre>
<p>You can replace <code>start</code> with <code>stop</code> to exit ghost or nginx if you have reason to do so, or <code>restart</code> if you need to reload one after making some sort of change. (e.g. editing Ghost&#8217;s <code>config.js</code> file requires that Ghost be restarted.) NGINX can reload its config files without doing a full restart of the process with <code>service nginx reload</code>, which takes less time and is useful when making edits.</p>
<p>If all went well, you should be able to open your Ghost blog in a browser.</p>
<h3>Managing Memory</h3>
<p>How much memory is Ghost using, you may wonder. And if you aren&#8217;t, you probably should. The enemy of performance on web servers is <a href="http://en.wikipedia.org/wiki/Paging">swapping</a>, which is where the system runs out of available RAM and starts copying things back and forth to the hard disk, causing major slowdowns. This is frequently referred to as &#8220;thrashing.&#8221; Even a fast solid state drive is orders of magnitude slower than RAM.</p>
<p>There are some useful tools for monitoring available RAM and inspecting active processes. The most commonly used ones are <code>free</code>, <code>top</code>, and <code>ps</code>.</p>
<p>The <code>free</code> command shows the system&#8217;s memory totals. If you run it with the <code>m</code> flag (<code>free -m</code>) to show the values in human-readable megabytes instead of plain bytes, you should see something like this:</p>
<pre class="brush: bash; title: ; notranslate">
root@DeepSpaceNine:~$ free -m
             total       used       free     shared    buffers     cached
Mem:           369        129        239          0         11         51
-/+ buffers/cache:         67        302
Swap:          767          0        767
</pre>
<p>The most important line is the one labeled <code>-/+ buffers/cache</code>. Modern operating systems don&#8217;t waste memory. If nothing else is making use of it, the OS will make use of it until the space is needed. The <code>-/+</code> line shows the usage sans caches. In this example, there are 302MB of free memory with only 67 being in use. There is also nothing in swap, which is exactly what you want to see.</p>
<p>The <code>top</code> command shows a live-updated table of currently running processes, and statistics for them. By default, it&#8217;s sorted by CPU activity, but you can sort by memory usage by pressing shift+M.</p>
<p style="text-align: center;"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-5237 imgborder" alt="The top command" src="//www.webmaster-source.com/wp-content/uploads/2013/11/ghost-top-cmd.png" width="600" height="381" /></p>
<p>Pressing control+C exits <code>top</code>.</p>
<p>Need to see a list of all running processes? Run <code>ps aux</code>. Be prepared for a huge list, as it will be full of system processes.</p>
<h3>Conclusion</h3>
<p>I hope this guide helps you get started with Ghost. I realize it is a bit technical, something the upcoming hosted service and DigitalOcean&#8217;s <a href="https://www.digitalocean.com/community/articles/how-to-use-the-digitalocean-ghost-application">one-click Ghost image</a> should help obviate, but hey, it&#8217;s new. It was harder to get up an running with WordPress back in 2003, too.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/11/06/installing-multiple-ghost-blogs-behind-nginx-on-ubuntu-12-04/feed/</wfw:commentRss>
		<slash:comments>242</slash:comments>
		</item>
		<item>
		<title>Solar Theme for Ghost Blogs</title>
		<link>https://www.webmaster-source.com/2013/10/17/solar-theme-for-ghost-blogs/</link>
		<comments>https://www.webmaster-source.com/2013/10/17/solar-theme-for-ghost-blogs/#comments</comments>
		<pubDate>Fri, 18 Oct 2013 02:34:56 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Ghost]]></category>
		<category><![CDATA[Theme]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5219</guid>
		<description><![CDATA[Need a stylish new design for your Ghost blog? Looking for something that puts your content first, with an emphasis on reducing eye strain? Allow me to introduce my new theme (which is technically a port of the one I made for Jekyll), based on the Solarized color palette. It includes stylesheets for the default [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Need a stylish new design for your <a href="http://ghost.org">Ghost</a> blog? Looking for something that puts your content first, with an emphasis on reducing eye strain? Allow me to introduce my new theme (which is technically a port of <a href="http://www.webmaster-source.com/2013/06/19/solar-a-jekyll-theme-based-on-the-solarized-color-palette/">the one I made for Jekyll</a>), based on the <a href="http://ethanschoonover.com/solarized">Solarized</a> color palette. It includes stylesheets for the default light-on-dark version, and for the alternate dark-on-light one.</p>
<p style="text-align: center;"><a href="http://www.webmaster-source.com/wp-content/uploads/2013/10/solar-ghost.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-medium wp-image-5220 imgborder" alt="Solar Theme for Ghost" src="//www.webmaster-source.com/wp-content/uploads/2013/10/solar-ghost-600x292.png" width="600" height="292" /></a></p>
<p>The theme is responsive, with a little bit of  JavaScript that collapses the left navigation into a &lt;select&gt; box on mobile-sized displays. It supports both uploadable logos (which replace them text-based heading at the top) and cover images, which appear at the very top of the page. Your author bio and profile picture appear in the sidebar when viewing a post page, as well.</p>
<h3>Installing the Theme</h3>
<ol>
<li><a href="https://github.com/mattvh/solar-theme-ghost/archive/master.zip">Download it here</a> (or clone it <a href="https://github.com/mattvh/solar-theme-ghost">on GitHub</a>)</li>
<li>Upload the <code>solar</code> directory to your Ghost blog&#8217;s <code>content/themes</code> folder.</li>
<li>Go to the Settings page of the Ghost backend and select <code>solar</code> from the Theme dropdown. Save the settings.</li>
</ol>
<p>Be sure to edit the <code>default.hbs</code> template to add or remove any links you want in the navigation list. You&#8217;ll probably want to insert the link to your own Twitter profile instead of leaving it as mine, and maybe add your other social networking profiles.</p>
<p><iframe src="http://ghbtns.com/github-btn.html?user=mattvh&amp;repo=solar-theme-ghost&amp;type=watch&amp;count=true&amp;size=large" height="30" width="170" frameborder="0" scrolling="0"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/10/17/solar-theme-for-ghost-blogs/feed/</wfw:commentRss>
		<slash:comments>167</slash:comments>
		</item>
		<item>
		<title>Ghost: The New Blogging Platform, and Why it Matters</title>
		<link>https://www.webmaster-source.com/2013/10/02/ghost-the-new-blogging-platform-and-why-it-matters/</link>
		<comments>https://www.webmaster-source.com/2013/10/02/ghost-the-new-blogging-platform-and-why-it-matters/#comments</comments>
		<pubDate>Thu, 03 Oct 2013 01:59:53 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Ghost]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5200</guid>
		<description><![CDATA[Ghost is a new blogging platform that aims to do one thing and do it well: blogging. Its developers want to recapture the spirit of blogging that was present in the earlier days, when it was all about writing and publishing long-form content. A return to the blog&#8217;s roots. Ghost has no complex content management [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-5201" alt="Ghost Logo" src="//www.webmaster-source.com/wp-content/uploads/2013/10/ghost-logo.png" width="196" height="135" /><a href="http://ghost.org">Ghost</a> is a new blogging platform that aims to do one thing and do it well: blogging. Its developers want to recapture the spirit of blogging that was present in the earlier days, when it was all about writing and publishing long-form content. A return to the blog&#8217;s roots. Ghost has no complex content management features that add bloat, and no Tumblr-like microblogging tools that encourage the reposted image echo-chamber that Tumblr has become. Just a minimalist, distraction-free writing environment, where you write in <a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>, with a live preview. (It also features a slick dashboard that resembles a classier version of Windows 8&#8217;s Metro UI.)</p>
<p>Ghost is simultaneously an attempt to mesh blogging&#8217;s roots with the state of the art. Eschewing PHP, Ghost is a Node.js app built upon the Express framework. All of the blogs I&#8217;ve visited thus far that are running Ghost have been very speedy, a feat that is difficult to pull off with WordPress, in my experience.<span id="more-5200"></span></p>
<h2>The Story</h2>
<p>Ghost is the brainchild of John O&#8217;Nolan, former Deputy Head of the WordPress UI team, who last year put together a <a href="http://john.onolan.org/ghost">series of wireframes</a> for a conceptual blogging platform that focused purely on writing and publishing, rather than enabling the management of any type of website under the sun.</p>
<blockquote><p>…it&#8217;s about publishing—which means writing—rather than mashing a few buttons to make sure that everyone can see and appreciate your latest funny picture/status, which is surely the most funny picture/status you&#8217;ve ever posted. — <em>John O&#8217;Nolan</em></p></blockquote>
<p>Just a few months later, the project was <a href="http://www.kickstarter.com/projects/johnonolan/ghost-just-a-blogging-platform">announced on Kickstarter.</a> It raised over 196,000 pounds during the campaign, well over the 25,000 pound goal.</p>
<p>Fast forward to the present and Ghost is <a href="http://blog.ghost.org/launch/">finally nearing its public release.</a> If all goes well, it should launch on <strong>October 14, 2013.</strong> It&#8217;s still a work in progress, and some things like the dashboard aren&#8217;t fully implemented yet, but the public will finally get to kick the tires and participate in the development.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-5202" alt="Ghost Editor" src="//www.webmaster-source.com/wp-content/uploads/2013/10/ghost-editor.png" width="600" height="344" /></p>
<h2>Why I&#8217;m Excited</h2>
<ul>
<li>I like Markdown. It&#8217;s a great way to write. I&#8217;ve tried <a href="http://jekyllrb.com/">Jekyll</a>, and while there&#8217;s a certain allure about <a href="http://www.webmaster-source.com/2012/05/09/full-circle-the-return-of-static-blog-generators/">static blogs,</a> there&#8217;s a slightly larger barrier to getting your post out than typing it in and pressing a button. I have a pretty good workflow set up for my <a href="http://matt.harzewski.com">personal blog,</a> but it&#8217;s still enough of a hassle to annoy me at times. Ghost has a beautiful editor that works exactly like <a href="http://mouapp.com/">Mou</a> the two-paned Markdown editor I wrote this post in.</li>
<li>I like the idea of a platform that is minimalistic, with plugins providing more functionality. It keeps the core leaner, which can only be good for performance.</li>
<li>Let&#8217;s face it, WordPress is full of <a href="http://en.wikipedia.org/wiki/Cruft">cruft</a>. The codebase is pretty clunky, mostly in the name of backwards compatibility with ancient (i.e. terrible) plugins that the core team doesn&#8217;t want to break. It has its own implementation of <a href="http://en.wikipedia.org/wiki/Magic_quotes">Magic Quotes</a> since recent versions of PHP ditched it, for crying out loud! The developers can redesign the interface all they want, but the kludgey codebase still lurks beneath.</li>
<li>While WordPress started out as a blogging tool, it&#8217;s become more like Drupal and other CMS frameworks that want to be the be-all, end-all tool used for managing complex websites. If you want a straight-up blog, it&#8217;s overkill. (Plus, I&#8217;m becoming more and more dissatisfied with PHP for various reasons.)</li>
<li>There are several major companies backing Ghost. Envato and WooThemes, to name the two that I find the most intriguing. There have been many upstarts in the blog platform arena over the year, but few have had major industry leaders backing them right out of the gate. That&#8217;s a pretty big deal.</li>
<li>It&#8217;s new, and I want to get under the hood and play with it!</li>
</ul>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-5203" alt="Ghost Dashboard" src="//www.webmaster-source.com/wp-content/uploads/2013/10/ghost-dashboard.png" width="600" height="399" /></p>
<p>&nbsp;</p>
<h2>But…What About Shared Hosting?</h2>
<p>The biggest recurring criticism I&#8217;ve seen voiced about Ghost is that it&#8217;s built on Node, while most of those cheap shared hosting offers from places like HostGator, GoDaddy, and their ilk are PHP-only.</p>
<p>Here&#8217;s the thing: cheap, commodity PHP hosting is—or should be—a thing of the past. Why pay $5-10/month for space on a slow, oversold shared server? You can pay $5/month for a VPS from <a href="https://www.digitalocean.com/pricing">DigitalOcean</a> with 512MB of RAM and 20GB of storage on an SSD. $10/month will get you a gigabyte of RAM and 30GB of storage.</p>
<p>For equal pricing to shared hosting, you can get a virtual server with guaranteed resources and full control over the box. It&#8217;s a no-brainer.</p>
<p>Sure, some people might not be comfortable setting a VPS up, but</p>
<ul>
<li>They can learn. It&#8217;s not difficult. You just need to run a few commands to install packages, maybe edit a few config files, and you&#8217;re done. If you can learn to install WordPress and use it, you can learn how to <code>apt-get install [whatever]</code>. Or in the case of businesses, hire someone who does.</li>
<li>Someone else can do it for them. I imagine this is often the case with people using shared hosts, anyway. Some shared hosts even use things like &#8220;Fantastico&#8221; to automatically install popular PHP scripts on their customers&#8217; accounts. Such a thing could be offered for a JavaScript-centered hosting environment as well.</li>
<li>A user who doesn&#8217;t need the flexibility of a self-hosted system can use a hosted solution. Just like many WordPress users opt to use WordPress.com, so may Ghost users. O&#8217;Nolan plans for such a service to be offered, eventually.</li>
</ul>
<p>Mark your calendars!</p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/10/02/ghost-the-new-blogging-platform-and-why-it-matters/feed/</wfw:commentRss>
		<slash:comments>137</slash:comments>
		</item>
		<item>
		<title>Finding a Website&#8217;s Favicon with Ruby</title>
		<link>https://www.webmaster-source.com/2013/09/25/finding-a-websites-favicon-with-ruby/</link>
		<comments>https://www.webmaster-source.com/2013/09/25/finding-a-websites-favicon-with-ruby/#comments</comments>
		<pubDate>Wed, 25 Sep 2013 11:46:02 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[favicon]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5187</guid>
		<description><![CDATA[For a project I&#8217;ve been working on, I wanted to to have my Sidekiq worker (which is part of an RSS crawler) discover the favicon for a web site and cache it for later display. It was fun figuring out a way to do this, so I just had to share. A Brief History of [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>For a project I&#8217;ve been working on, I wanted to to have my <a href="http://sidekiq.org/">Sidekiq</a> worker (which is part of an RSS crawler) discover the favicon for a web site and cache it for later display. It was fun figuring out a way to do this, so I just had to share.</p>
<h3>A Brief History of Favicons</h3>
<p><a href="http://en.wikipedia.org/wiki/Favicon">Favicons</a>, or &#8220;shortcut icons,&#8221; can be defined in multiple ways. Like all too many things in web design, browsers handle them in slightly different and mildly incompatible ways, meaning there&#8217;s plenty of redundancy. Favicons came to be when Microsoft added them to Internet Explorer 5 in 1999, implementing a feature where the browser would check the server for a file named <code>favicon.ico</code> and display it in certain parts of the UI. The following year, the W3C published a standard method for defining a favicon. Rather than simply having the browser look for a file in the root directory, an HTML document should specify a file in the header with a <code>&lt;link&gt;</code> tag, just like with stylesheets.<span id="more-5187"></span></p>
<p>Fast forward to the present, and you have a bit of screwiness.</p>
<ul>
<li>All major web browsers check for the link tag first, and fall back to <code>favicon.ico</code> if it&#8217;s not found.</li>
<li>You can define multiple icons in the HTML header. You can have ICO/PNG/GIF formats, as well as different sizes.</li>
<li>Some browsers support larger 32&#215;32 favicons, while others will only use the 16&#215;16 ones. Chrome for Mac prefers the 32&#215;32 ones, and scales them down to 16&#215;16 on Macs without Retina displays.</li>
<li>Big Bad Internet Explorer only supports ICO files for favicons, not PNGs.</li>
</ul>
<p>The most compatible way to set up your favicon is to define both 32&#215;32 and 16&#215;16 icons in your header, using the PNG format, and make a 16&#215;16 ICO formatted one to name &#8220;favicon.ico&#8221; and drop into your web root. Browsers that play nicely will use the PNG ones in whatever dimensions they prefer, and IE will fall back to the ICO file.</p>
<h3>Writing the Class</h3>
<p>Now that the history lesson is out of way, you can see why there&#8217;s a little bit of a challenge here. Depending on how badly you want to find and display that icon, you may have to write logic for the different methods. For this tutorial, I will focus on two. The simplest, which is looking to see if there&#8217;s a <code>favicon.ico</code>, and a basic implementation of checking for a link tag defining a shortcut icon.</p>
<p>Before we do anything else, we need to install a few dependencies. Either add them to your Gemfile and do a <code>bundle install</code>, or use the <code>gem install</code> command to install them manually.</p>
<ul>
<li><a href="http://johnnunemaker.com/httparty/">HTTParty</a> (<code>gem install httparty</code>)</li>
<li><a href="http://nokogiri.org/">Nokogiri</a> (<code>gem install nokogiri</code>)</li>
</ul>
<p>Now require the necessary libraries at the top of a new Ruby file and we can get going.</p>
<pre class="brush: ruby; title: ; notranslate">
require &quot;httparty&quot;
require &quot;nokogiri&quot;
require &quot;base64&quot;
</pre>
<p>We can define a class to make a nice, clean interface for this to keep it modular and easier to reuse. As you can see below, I&#8217;ve made a <code>Favicon</code> class and added some accessors for instance variables, as well as an <code>initialize</code> method that assigns the parameter it receives to the <code>@host</code> instance variable before calling the method we will be defining next.</p>
<pre class="brush: ruby; title: ; notranslate">
require &quot;httparty&quot;
require &quot;nokogiri&quot;
require &quot;base64&quot;


class Favicon


  attr_reader :host
  attr_reader :uri
  attr_reader :base64


  def initialize(host)
    @host = host
    check_for_ico_file
  end


end
</pre>
<p>We&#8217;ll be implementing the simplest part first. The <code>check_for_ico_file</code> method will send an HTTP GET request to <code>/favicon.ico</code> on the server specified in @host and check to see if a file exists. (The server will send a <code>200 OK</code> response if it does, and a <code>404 Not Found</code> error otherwise.) If it does, the URL will be saved to an instance variable and the icon file&#8217;s contents will be base64 encoded before being saved to an instance variable as well.</p>
<p>The HTTParty gem is great for this, since it drastically simplifies simple HTTP requests like this.</p>
<pre class="brush: ruby; title: ; notranslate">
# Check /favicon.ico
def check_for_ico_file
  uri = URI::HTTP.build({:host =&gt; @host, :path =&gt; '/favicon.ico'}).to_s
  res = HTTParty.get(uri)
  if res.code == 200
    @base64 = Base64.encode64(res.body)
    @uri = uri
  end
end
</pre>
<p>If you want, you could go ahead and instantiate the class to try out what we have so far. If you pass it the domain name of a site that uses the <code>/favicon.ico</code> convention, the object should find it without issue.</p>
<pre class="brush: ruby; title: ; notranslate">
favicon = Favicon.new(&quot;arstechnica.com&quot;)

puts favicon.uri
#Outputs http://arstechnica.com/favicon.ico

puts favicon.base64
#Outputs a bunch of base64-encoded gibberish. More on this later

puts puts favicon.host
#Outputs arstechnica.com
</pre>
<p>Now let&#8217;s handle link tags! The process for that is a little bit more in-depth. First we need to request a web page from the server, such as the index page, and parse it for tags that resemble <code>&lt;link rel="shortcut icon" href="..." /&gt;</code>. Then we have to evaluate the contents of <code>href</code> to make sure it&#8217;s an absolute URL, and prepend the domain name if it is not. After that, we can finally make a request to get the icon itself and save it.</p>
<p>Still with me? Excellent, now here&#8217;s the code to do that. I&#8217;ll comment it a little more thoroughly, since it looks messier at a glance.</p>
<pre class="brush: ruby; title: ; notranslate">
# Check &quot;shortcut icon&quot; tag
def check_for_html_tag

  # Load the index page with HTTParty and pass the contents to Nokogiri for parsing
  uri = URI::HTTP.build({:host =&gt; @host, :path =&gt; '/'}).to_s
  res = HTTParty.get(uri)
  doc = Nokogiri::HTML(res)

  # Use an xpath expression to tell Nokogiri what to look for.
  doc.xpath('//link[@rel=&quot;shortcut icon&quot;]').each do |tag|

    # This is the contents of the &quot;href&quot; attribute, which we pass to Ruby's URI module for analysis
    taguri = URI(tag['href'])

    unless taguri.host.to_s.length &lt; 1
      # There is a domain name in taguri, so we're good
      iconuri = taguri.to_s
    else
      # There is no domain name in taguri. It's a relative URI!
      # So we have to join it with the index URL we built at the beginning of the method
      iconuri = URI.join(uri, taguri).to_s
    end

    # Grab the icon and set the instance variables
    res = HTTParty.get(iconuri)
    if res.code == 200
      @base64 = Base64.encode64(res.body)
      @uri = iconuri
    end
    
  end

end
</pre>
<p>Now there&#8217;s one more thing to do before we&#8217;re done. The initialize method needs to be tweaked so it calls our newest method:</p>
<pre class="brush: ruby; title: ; notranslate">
def initialize(host)
  @host = host
  check_for_ico_file
  check_for_html_tag
end
</pre>
<p>Now the class will check for the <code>favicon.ico</code> file first, then the HTML tag. If the HTML tag is present, it will take precedence.</p>
<p class="alertbubble"><strong>Available as a Gist!</strong> For your convenience, the results of this tutorial are <a href="https://gist.github.com/redwallhp/6692349">available as a GitHub Gist.</a></p>
<p></p>
<h3>Using the Class</h3>
<p>Now all you have to do is include the class with a require statement, and grab favicons.</p>
<pre class="brush: ruby; title: ; notranslate">
require &quot;favicon&quot;

favicon = Favicon.new(&quot;arstechnica.com&quot;)

puts favicon.uri
#Outputs http://static.arstechnica.net/favicon.ico

puts favicon.base64
#Outputs a bunch of base64-encoded gibberish. More on this later

puts puts favicon.host
#Outputs arstechnica.com
</pre>
<p>Now&#8230;what of that &#8220;base64-encoded gibberish?&#8221; It&#8217;s the perfect format for a little trick called Data URIs, which you can <a href="http://css-tricks.com/data-uris/">read all about over at CSS-Tricks</a>. If you cache that base64 string somewhere, probably in a database, you can output it like so:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;img width=&quot;16&quot; height=&quot;16&quot; alt=&quot;favicon&quot; src=&quot;data:image/gif;base64,BLAHBBLAHGIBBERISHGOESHERE&quot; /&gt;
</pre>
<p>It will display like any other image, but won&#8217;t use an additional HTTP request, because the image data is already embedded on the page. This makes it perfect for a list of web sites with icons beside them. Instead of kicking off several HTTP requests for individual tiny images, you just embed them right in the page.</p>
<p>If you&#8217;re unfortunate enough that you must support antique versions of Internet Explorer (version seven or prior) then you can&#8217;t use Data URIs, as they were not supported. However, all is not lost. You could conceivably adapt the class and have it write the image data to files on the server instead of base64-encoding them.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/09/25/finding-a-websites-favicon-with-ruby/feed/</wfw:commentRss>
		<slash:comments>101</slash:comments>
		</item>
		<item>
		<title>Setting Up a LESS Workflow in Sublime Text</title>
		<link>https://www.webmaster-source.com/2013/08/28/setting-up-a-less-workflow-in-sublime-text/</link>
		<comments>https://www.webmaster-source.com/2013/08/28/setting-up-a-less-workflow-in-sublime-text/#comments</comments>
		<pubDate>Wed, 28 Aug 2013 11:16:17 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[LESS]]></category>
		<category><![CDATA[Sublime Text]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5165</guid>
		<description><![CDATA[LESS has been a popular way to streamline your CSS-writing for a while now, but fitting it into your workflow isn&#8217;t always easy. Some designers use standalone applications like CodeKit or SimpLESS to compile their LESS files into browser-ready CSS, but I prefer a more integrated approach. Fortunately, Sublime Text—my personal favorite text editor has [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://lesscss.org/">LESS</a> has been a popular way to streamline your CSS-writing for a while now, but fitting it into your workflow isn&#8217;t always easy. Some designers use standalone applications like <a href="http://incident57.com/codekit/">CodeKit</a> or <a href="http://wearekiss.com/simpless">SimpLESS</a> to compile their LESS files into browser-ready CSS, but I prefer a more integrated approach. Fortunately, <a href="http://www.sublimetext.com/">Sublime Text</a>—my personal favorite text editor has several available extensions to build LESS support in.<span id="more-5165"></span></p>
<p>I will assume that you already have <a href="http://wbond.net/sublime_packages/package_control">Sublime Package Control</a> installed, since it is pretty much a given for Sublime Text users.</p>
<h3>Step 1: Adding Syntax Highlighting</h3>
<p>I can&#8217;t imagine why anybody <em>wouldn&#8217;t</em> want their LESS files to have the proper syntax highlighting, so you probably want to install the <strong>LESS-sublime</strong> package, which you can find in Sublime Package Control under &#8220;LESS.&#8221;</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  src="//www.webmaster-source.com/wp-content/uploads/2013/08/stless-install-package.png" alt="Install Package" width="600" height="70" class="aligncenter size-full wp-image-5166 imgborder" /></p>
<h3>Step 2: Installing LESSC</h3>
<p>Now you need to install the LESS compiler, but first you need to grab a couple of dependencies.</p>
<p>First, download and install <a href="http://nodejs.org/">Node.js</a>. NPM (Node Package Manager) should also be installed automatically, so now you should be ready to install LESSC. Simply run the following command:</p>
<pre class="brush: plain; title: ; notranslate">npm install -g less</pre>
<h3>Step 3: Installing a LESS Build System</h3>
<p>In order to have your LESS files compiled into CSS, you will want to install the <a href="https://github.com/berfarah/LESS-build-sublime">LESS-build</a> package. Once it&#8217;s properly set up, it adds a Build System for LESS, enabling you to process the files by pressing Control+B (Command+B for Mac users).</p>
<p>After you have installed the package, you need to do a little configuration.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  src="//www.webmaster-source.com/wp-content/uploads/2013/08/stless-browse-packages.png" alt="Browse Packages" width="506" height="136" class="aligncenter size-full wp-image-5167 imgborder" /></p>
<ol>
<li>Open the package directory by typing &#8220;browse packages&#8221; into the command palette and selecting the LESS-build folder.</li>
<li>Run <code>changeLESSBuildType.bat</code> (Windows) or <code>changeLESSBuildType.sh</code> (Mac/Linux) to set the build mode. Pick option number two (&#8220;directory rewrite&#8221;) when prompted.</li>
<li>In your project, select &#8220;LESS&#8221; from the Tools &gt; Build System menu.</li>
</ol>
<h3>Step 4: Using Your New Setup</h3>
<p>To demonstrate how the finished setup works, I put together a quick project in Sublime Text. My simple <code>index.html</code> references <code>css/mysite.css</code> as its stylesheet. This is the compiled output of many LESS files, which are found in the <code>less</code> directory.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  src="//www.webmaster-source.com/wp-content/uploads/2013/08/stless-st-overview.png" alt="Sublime Text LESS Overview" width="600" height="303" class="aligncenter size-full wp-image-5168 imgborder" /></p>
<p>The <code>less/mysite.less</code> file, which is compiled into <code>css/mysite.css</code> when I switch to it and press Command+B, looks like this:</p>
<pre class="brush: css; title: ; notranslate">
//Load Twitter Bootstrap

@import &quot;bootstrap/bootstrap.less&quot;;

//Additional styles would go here
</pre>
<p>It loads the LESS files that make up <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a>, which are easily tweak-able, since all of the styles are split into different files by sensible categories. Then any styles placed after the import line would override Bootstrap&#8217;s if they conflicted, given CSS&#8217;s precedence rules.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/08/28/setting-up-a-less-workflow-in-sublime-text/feed/</wfw:commentRss>
		<slash:comments>125</slash:comments>
		</item>
		<item>
		<title>Solar: A Jekyll Theme Based on the Solarized Color Palette</title>
		<link>https://www.webmaster-source.com/2013/06/19/solar-a-jekyll-theme-based-on-the-solarized-color-palette/</link>
		<comments>https://www.webmaster-source.com/2013/06/19/solar-a-jekyll-theme-based-on-the-solarized-color-palette/#comments</comments>
		<pubDate>Wed, 19 Jun 2013 11:04:29 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Jekyll]]></category>
		<category><![CDATA[Themes]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5120</guid>
		<description><![CDATA[I&#8217;ve been having fun playing around with Jekyll and Ruby lately, which has lead to a sudden increase in the number of repositories on my GitHub profile. After converting my personal blog and porting its theme over, I thought it would be fun to build a fresh theme and release it to the public. Without [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been having fun playing around with <a href="http://jekyllrb.com/">Jekyll</a> and Ruby lately, which has lead to a sudden increase in the number of repositories on my GitHub profile. After converting my personal blog and porting its theme over, I thought it would be fun to build a fresh theme and release it to the public.</p>
<p>Without further ado, I would like to introduce <a href="https://github.com/mattvh/solar-theme-jekyll">Solar</a>, a theme I based upon the <a href="http://ethanschoonover.com/solarized">Solarized</a> color palette. It includes stylesheets for both Solarized Dark and Solarized Light, since the colors are defined separately from the page structure. It&#8217;s responsive, all the way down to mobile size, and it&#8217;s built with link-blogging in mind.</p>
<p style="text-align: center;"><a href="https://github.com/mattvh/solar-theme-jekyll"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="size-full wp-image-5121 aligncenter imgborder" alt="Solar Theme" src="//www.webmaster-source.com/wp-content/uploads/2013/06/solar-theme.png" width="600" height="451" /></a></p>
<p>You can view <a href="http://mattvh.github.io/solar-theme-jekyll/">a demo of Solar here</a>, and <a href="https://github.com/mattvh/solar-theme-jekyll">download it on GitHub</a>. It&#8217;s licensed under the GPL, so feel free to fork it and go crazy.</p>
<p><iframe src="http://ghbtns.com/github-btn.html?user=mattvh&#038;repo=solar-theme-jekyll&#038;type=watch&#038;count=true&#038;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="170" height="30"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/06/19/solar-a-jekyll-theme-based-on-the-solarized-color-palette/feed/</wfw:commentRss>
		<slash:comments>84</slash:comments>
		</item>
		<item>
		<title>DigitalOcean Review</title>
		<link>https://www.webmaster-source.com/2013/06/12/digitalocean-review/</link>
		<comments>https://www.webmaster-source.com/2013/06/12/digitalocean-review/#comments</comments>
		<pubDate>Wed, 12 Jun 2013 21:32:49 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Hosting]]></category>
		<category><![CDATA[DigitalOcean]]></category>
		<category><![CDATA[VPS]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5104</guid>
		<description><![CDATA[Since the beginning of April, this site has been hosted by DigitalOcean. I&#8217;ve been a longtime customer of VPS.net—from September of 2009 up until April of 2012—but the difference in service was so huge that I had to switch. While VPS.net was a good choice back in 2009, when I chose them over the then-comparable [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  class="alignright size-full wp-image-5107" alt="DigitalOcean" src="//www.webmaster-source.com/wp-content/uploads/2013/05/digitalocean-logo.png" width="167" height="112" />Since the beginning of April, this site has been hosted by <a href="https://www.digitalocean.com/">DigitalOcean</a>. I&#8217;ve been a longtime customer of VPS.net—from September of 2009 up until April of 2012—but the difference in service was so huge that I had to switch. While VPS.net was a good choice back in 2009, when I chose them over the then-comparable Linode, their competition has outpaced them over the years. I&#8217;m now getting substantially more for half the price. It was a big decision to move, but I&#8217;m glad I did.</p>
<p>History lesson aside, here&#8217;s what DigitalOcean has to offer: affordable VPS hosting with plenty of memory and fast solid-state drives. Their offerings are comparable to those of the venerable <a href="https://www.linode.com/">Linode</a>, though cheaper. (The difference comes down to which is more important to you: CPU or price.)</p>
<p>Their cheapest plan gets you a VM with 512MB of RAM and 20GB of space for a mere five dollars per month (or $0.007/hour). That&#8217;s cheaper than a lot of shared hosting plans, for a speedy box with full root access. The plan I&#8217;m using is their $10/month option, which comes with one gigabyte of memory.</p>
<p style="text-align: center;"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-5106 imgborder" alt="DigitalOcean Pricing" src="//www.webmaster-source.com/wp-content/uploads/2013/05/digitalocean-pricing.png" width="600" height="491" /></p>
<p>Backups and snapshots of VMs are priced reasonably, with backups costing 20% of the server&#8217;s price (e.g. $1 per month for a $5 per month server) and snapshots being $0.02 per gigabyte stored.</p>
<p>The service has been stable so far, and the one support ticket I opened was resolved in a timely manner. Performance-wise, there has been a definite improvement over my previous host. (It&#8217;s also nice having the server be in New York, which results in a much more favorable network latency from where I live.)</p>
<p>DigitalOcean has a freshly redesigned control panel, from which you can manage your servers, DNS, billing and other settings. It&#8217;s also the place where you can set up your API access if you want to manage things from a mobile app, command line utility, or even use a Vagrant provider.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-5108" alt="DigitalOcean Control Panel" src="//www.webmaster-source.com/wp-content/uploads/2013/05/digitalocean-controlpanel.png" width="600" height="375" /></p>
<p>I&#8217;ve been very happy with DigitalOcean since my big switch, and definitely recommend them if you&#8217;re in the market for a decent VPS provider. If you want to give them a try, <a href=" https://www.digitalocean.com/?refcode=b6711983671a ">here&#8217;s my affiliate link</a>. If you enter the promo code SSDPOWER on the billing settings page, you&#8217;ll get $10 worth of free credit. You can spin up a VM, play around with it, and delete it when you&#8217;re done.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/06/12/digitalocean-review/feed/</wfw:commentRss>
		<slash:comments>565</slash:comments>
		</item>
		<item>
		<title>Using the WordPress 3.5 Media Uploader in Your Plugin or Theme</title>
		<link>https://www.webmaster-source.com/2013/02/06/using-the-wordpress-3-5-media-uploader-in-your-plugin-or-theme/</link>
		<comments>https://www.webmaster-source.com/2013/02/06/using-the-wordpress-3-5-media-uploader-in-your-plugin-or-theme/#comments</comments>
		<pubDate>Wed, 06 Feb 2013 11:21:50 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Themes]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=5001</guid>
		<description><![CDATA[Back in 2010, I wrote a post on Using the WordPress Uploader in Your Plugin or Theme that went on to be one of my most popular tutorials of all time. Then the WordPress team went and added a much cooler media uploader in version 3.5 and make that post outdated. Since most of you [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Back in 2010, I wrote a post on <a href="http://www.webmaster-source.com/2010/01/08/using-the-wordpress-uploader-in-your-plugin-or-theme/">Using the WordPress Uploader in Your Plugin or Theme</a> that went on to be one of my most popular tutorials of all time. Then the WordPress team went and added a much cooler media uploader in version 3.5 and make that post outdated. Since most of you probably want to add the <em>new</em> uploader in a theme or plugin you&#8217;re working on right now, I figured it was time for an updated post.</p>
<p style="text-align: center"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-5002 imgborder" alt="WordPress 3.5 Media Uploader" src="//www.webmaster-source.com/wp-content/uploads/2013/02/wp35mediauploader.png" width="600" height="286" /></p>
<p>The process required to add the new uploader is a bit different, but not too much more difficult. I was able to adapt the old tutorial a little, so it shouldn&#8217;t be too hard to replace some code in an existing project and get the new uploader instead of the old.<span id="more-5001"></span></p>
<p>For the sake of simplicity, let&#8217;s start with the same HTML snippet as in the old tutorial. This goes along with the rest of the HTML for your admin page, or wherever in the admin you&#8217;re trying to add an upload field.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;label for=&quot;upload_image&quot;&gt;
	&lt;input id=&quot;upload_image&quot; type=&quot;text&quot; size=&quot;36&quot; name=&quot;ad_image&quot; value=&quot;http://&quot; /&gt; 
	&lt;input id=&quot;upload_image_button&quot; class=&quot;button&quot; type=&quot;button&quot; value=&quot;Upload Image&quot; /&gt;
	&lt;br /&gt;Enter a URL or upload an image
&lt;/label&gt;
</pre>
<p>Now we need to load up the necessary JavaScript files.</p>
<pre class="brush: php; title: ; notranslate">
add_action('admin_enqueue_scripts', 'my_admin_scripts');

function my_admin_scripts() {
	if (isset($_GET['page']) &amp;&amp; $_GET['page'] == 'my_plugin_page') {
		wp_enqueue_media();
		wp_register_script('my-admin-js', WP_PLUGIN_URL.'/my-plugin/my-admin.js', array('jquery'));
		wp_enqueue_script('my-admin-js');
	}
}
</pre>
<p>We bind the <code>my_admin_scripts()</code> function to the <code>admin_enqueue_scripts</code> hook, and enqueue both the media scripts and our own JavaScript file. Also, the scripts will only be loaded if the current page is equal to &#8220;my_plugin_page,&#8221; which you would of course replace with the slug your <a href="http://codex.wordpress.org/Administration_Menus">admin menu</a> has.</p>
<p>Now for the complicated part: the script that hooks into the uploader. Continuing with the above example, it would be named <code>my-admin.js</code>.</p>
<pre class="brush: jscript; title: ; notranslate">
jQuery(document).ready(function($){


	var custom_uploader;


	$('#upload_image_button').click(function(e) {

		e.preventDefault();

		//If the uploader object has already been created, reopen the dialog
		if (custom_uploader) {
			custom_uploader.open();
			return;
		}

		//Extend the wp.media object
		custom_uploader = wp.media.frames.file_frame = wp.media({
			title: 'Choose Image',
			button: {
				text: 'Choose Image'
			},
			multiple: false
		});

		//When a file is selected, grab the URL and set it as the text field's value
		custom_uploader.on('select', function() {
			attachment = custom_uploader.state().get('selection').first().toJSON();
			$('#upload_image').val(attachment.url);
		});

		//Open the uploader dialog
		custom_uploader.open();

	});


});
</pre>
<p>When the button is clicked, it creates a new instance of the <code>wp.media</code> object and configures it to only accept a single file, since the text field can only hold one file URL. Then it binds a function to the selection action, which gets the file attributes when an image is chosen and sets the <code>#upload_image</code> text field value to the file&#8217;s URL.</p>
<p>Providing everything went as expected, you should have a form field that will accept an arbitrary URL, or allow the user to upload one.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  src="//www.webmaster-source.com/wp-content/uploads/2013/02/wp35mediauploader-field.png" alt="File Upload Field" width="352" height="44" class="aligncenter size-full wp-image-5005" /></p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/02/06/using-the-wordpress-3-5-media-uploader-in-your-plugin-or-theme/feed/</wfw:commentRss>
		<slash:comments>70</slash:comments>
		</item>
		<item>
		<title>Post to Twitter From a PHP Script: 2013 Edition</title>
		<link>https://www.webmaster-source.com/2013/01/09/post-to-twitter-from-a-php-script-2013-edition/</link>
		<comments>https://www.webmaster-source.com/2013/01/09/post-to-twitter-from-a-php-script-2013-edition/#comments</comments>
		<pubDate>Wed, 09 Jan 2013 11:18:20 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=4956</guid>
		<description><![CDATA[Back in 2009, I wrote a post on how to write a simple PHP script to call on the Twitter API and update your status. Despite its popularity, the information hasn&#8217;t been relevant in some time. (Things certainly have changed since then!) The Twitter API has changed a lot over the years, and it&#8217;s not [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Back in 2009, <a href="http://www.webmaster-source.com/2009/04/05/post-to-twitter-from-a-php-script/">I wrote a post</a> on how to write a simple PHP script to call on the Twitter API and update your status. Despite its popularity, the information hasn&#8217;t been relevant in some time. (Things certainly have changed since then!) The Twitter API has changed a lot over the years, and it&#8217;s not so simple that you can get a newbie up and running with a few lines of code.</p>
<p>The mandatory usage of OAuth tokens, rather than a simple username and password combination, for API requests has greatly strengthened account security, but it&#8217;s one of the prime hurdles complicating the process. More recently, XML support was removed in favor of JSON, URL structures changed to include an API version, and authentication is now required for every request.</p>
<p>Fortunately, you don&#8217;t <em>have</em> to deal with the little details. You can use a library that does the heavy lifting for you, rather than reinventing the wheel. Sure, there are resources to learn how to do it the hard way, but I assume that you want a quicker solution if you&#8217;re reading this.</p>
<h3>Step 1: Download tmhOAuth</h3>
<p>Download the tmhOAuth library <a href="https://github.com/themattharris/tmhOAuth">from GitHub</a>. This package will handle interactions with the Twitter API once you include it from your script. (It requires at least PHP 5.1.2 and the cURL extension.)</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-4957" alt="Download tmhOAuth" src="//www.webmaster-source.com/wp-content/uploads/2012/12/post2twitter-tmhoauth.jpg" width="596" height="213" /></p>
<p><span id="more-4956"></span></p>
<h3>Step 2: Include the Library in Your Project</h3>
<p>First, drop the required files into your project folder. You could simply move the entire download in and rename it, or if you just want the essentials, the required files are <code>tmhOAuth.php</code> and <code>cacert.pem</code>.</p>
<p style="text-align: center;"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-4958 imgborder" alt="Including tmhOauth" src="//www.webmaster-source.com/wp-content/uploads/2012/12/post2twitter-dirstructure.png" width="600" height="140" /></p>
<p>Now, you need to include the files in your PHP script. All you need is an include line at the top.</p>
<pre class="brush: php; title: ; notranslate">
include 'tmhOAuth/tmhOAuth.php';
</pre>
<h3>Step 3: Get Your Tokens</h3>
<p>We need to make a short detour, now. In order to give your script permission to update your status, you need to generate some authorization tokens for it. Head over to <a href="http://dev.twitter.com/apps">dev.twitter.com/apps</a> and log in to your Twitter account.</p>
<p>Click the big &#8220;Create a new application&#8221; button and fill in the required fields on the resulting screen. All you need is an application name to identify your script, a brief description, and the URL it will reside at.</p>
<p>Once you agree to the terms of service and submit the form, select the Settings tab on the resulting screen. Change the access type from Read Only to Read and Write before saving the settings.</p>
<p>Flipping back to the Details tab, you now need to scroll down to the OAuth settings section. You will need the consumer key and consumer secret, as well as the access token and access secret from the following section.</p>
<p>After the include lines, you need to instantiate the tmhOAuth class with the tokens, like so:</p>
<pre class="brush: php; title: ; notranslate">
$tmhOAuth = new tmhOAuth(array(
  'consumer_key' =&gt; 'THE_CONSUMER_KEY',
  'consumer_secret' =&gt; 'THE_CONSUMER_SECRET',
  'token' =&gt; 'THE_ACCESS_TOKEN',
  'secret' =&gt; 'THE_ACCESS_TOKEN_SECRET',
));
</pre>
<p>This readies tmhOAuth to interact with the API through your account. (Allowing <em>other</em> Twitter users to log in and grant permission is beyond the scope of this tutorial. But <a href="http://net.tutsplus.com/tutorials/php/creating-a-twitter-oauth-application/">Tuts+ has you covered</a> if you want a more advanced tutorial.)</p>
<h3>Step 4: Sending the Tweet</h3>
<p>To send a tweet, all you have to do now is call the <code>request</code> method and pass the required arguments.</p>
<pre class="brush: php; title: ; notranslate">
$response = $tmhOAuth-&gt;request('POST', $tmhOAuth-&gt;url('1.1/statuses/update'), array(
  'status' =&gt; 'Test message. Lorem ipsum.'
));
</pre>
<p>You can, of course, replace the message with anything you want (providing it&#8217;s under 140 characters) and even use a dynamic variable instead of a static string.</p>
<h3>Step 5: Verify Success</h3>
<p>Now let&#8217;s see if Twitter accepted the request and successfully updated your status.</p>
<pre class="brush: php; title: ; notranslate">
if ($response != 200) {
	//Do something if the request was unsuccessful
	echo 'There was an error posting the message.';
}
</pre>
<h3>Conclusion</h3>
<p>That wasn&#8217;t too difficult, was it? While it&#8217;s a simple example, it should help you get started in the right direction. The tmhOAuth library can handle just about any Twitter API request you may need to make, and the GitHub repository includes plenty of examples to browse through.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/01/09/post-to-twitter-from-a-php-script-2013-edition/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Best of 2012</title>
		<link>https://www.webmaster-source.com/2013/01/01/best-of-2012/</link>
		<comments>https://www.webmaster-source.com/2013/01/01/best-of-2012/#comments</comments>
		<pubDate>Tue, 01 Jan 2013 23:59:29 +0000</pubDate>
		<dc:creator><![CDATA[Matt]]></dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.webmaster-source.com/?p=4961</guid>
		<description><![CDATA[Today Webmaster-Source enters its seventh year. Historically I have done a quick roundup of some of the more interesting posts from the previous year, and I intend to continue with that tradition going into the new year. So, without further ado, let us recap. January Alternatives to GitHub Git: The Simple Guide Learning Curve: It [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Today Webmaster-Source enters its seventh year. Historically I have done a quick roundup of some of the more interesting posts from the previous year, and I intend to continue with that tradition going into the new year.</p>
<p>So, without further ado, let us recap.</p>
<h3>January</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/01/11/alternatives-to-github/">Alternatives to GitHub</a></li>
<li><a href="http://www.webmaster-source.com/2012/01/19/git-the-simple-guide/">Git: The Simple Guide</a></li>
<li><a href="http://www.webmaster-source.com/2012/01/27/learning-curve-it-isnt-what-you-think-it-is/">Learning Curve: It isn’t What You Think it is</a></li>
</ul>
<h3>February</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/02/06/crowd-favorites-wordpress-post-formats-admin-ui/">Crowd Favorite’s WordPress Post Formats Admin UI</a></li>
<li><a href="http://www.webmaster-source.com/2012/02/09/how-much-does-amazon-cloudfront-cost-for-a-small-blog/">How Much Does Amazon CloudFront Cost for a Small Blog?</a></li>
<li><a href="http://www.webmaster-source.com/2012/02/16/css1k-what-can-you-do-with-1kb-of-css/">CSS1K: What Can You Do With 1KB of CSS?</a></li>
<li><a href="http://www.webmaster-source.com/2012/02/22/adventures-in-buying-expiring-domains/">Adventures in Buying Expiring Domains</a></li>
</ul>
<h3>March</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/03/05/what-is-a-kibibyte/">What is a Kibibyte?</a></li>
<li><a href="http://www.webmaster-source.com/2012/03/08/scripting-news-hits-15-year-mark-and-other-really-old-websites/">Scripting News Hits 15 Year Mark, and Other Really Old Websites</a></li>
<li><a href="http://www.webmaster-source.com/2012/03/13/what-to-do-after-you-install-ubuntu-server-in-vmwware-fusion/">What to Do After You Install Ubuntu Server in VMwware Fusion</a></li>
<li><a href="http://www.webmaster-source.com/2012/03/22/prediction-higher-resolution-macbooks-soon-to-come/">Prediction: Higher Resolution MacBooks Soon to Come</a> — Well, that was a solid prediction, wasn&#8217;t it?</li>
<li><a href="http://www.webmaster-source.com/2012/03/29/browserquest-a-massively-multiplayer-game-in-html5-and-javascript/">BrowserQuest: A Massively Multiplayer Game in HTML5 and JavaScript</a></li>
</ul>
<p><span id="more-4961"></span></p>
<h3>April</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/04/03/how-to-flip-a-page-upside-down-with-css/">How to Flip a Page Upside-Down with CSS</a></li>
<li><a href="http://www.webmaster-source.com/2012/04/11/bobby-tables-com-a-guide-to-preventing-sql-injection/">Bobby-Tables.com: A guide to preventing SQL injection</a></li>
<li><a href="http://www.webmaster-source.com/2012/04/24/pure-css-blockquote-styling/">Pure CSS Blockquote Styling</a></li>
</ul>
<h3>May</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/05/01/disabling-comments-on-old-posts-or-how-to-kill-discussion/">Disabling Comments on Old Posts, or How to Kill Discussion</a></li>
<li><a href="http://www.webmaster-source.com/2012/05/09/full-circle-the-return-of-static-blog-generators/">Full Circle: The Return of Static Blog Generators</a></li>
<li><a href="http://www.webmaster-source.com/2012/05/20/meet-webmaster-source-6-0/">Meet Webmaster-Source 6.0</a></li>
<li><a href="http://www.webmaster-source.com/2012/05/28/10-web-apps-for-web-design/">10 Web Apps for Web Design</a></li>
</ul>
<h3>June</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/06/04/animating-a-css-sprite-with-javascript/">Animating a CSS Sprite With JavaScript</a></li>
<li><a href="http://www.webmaster-source.com/2012/06/11/wordpress-post-thumbnails-migrating-from-custom-fields-to-the-featured-image-api/">WordPress Post Thumbnails: Migrating from Custom Fields to the Featured Image API</a></li>
<li><a href="http://www.webmaster-source.com/2012/06/21/commonly-misused-proverbs/">Commonly Misused Proverbs</a></li>
</ul>
<h3>July</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/07/05/checking-the-status-of-a-minecraft-server-with-php/">Checking the Status of a Minecraft Server with PHP</a></li>
<li><a href="http://www.webmaster-source.com/2012/07/10/find-an-images-dimensions-and-mime-type-with-php/">Find an Image’s Dimensions and MIME Type with PHP</a></li>
<li><a href="http://www.webmaster-source.com/2012/07/17/handling-file-uploads-with-php/">Handling File Uploads with PHP</a></li>
<li><a href="http://www.webmaster-source.com/2012/07/24/blogs-are-the-next-big-social-network/">Blogs are the Next Big Social Network</a></li>
<li><a href="http://www.webmaster-source.com/2012/07/31/try-git-learn-git-in-15-minutes-with-an-interactive-tutorial/">Try Git: Learn Git in 15 Minutes with an Interactive Tutorial</a></li>
</ul>
<h3>August</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/08/06/digg-is-back-with-a-new-take-and-new-ownership/">Digg is Back, with a New Take and New Ownership</a></li>
<li><a href="http://www.webmaster-source.com/2012/08/09/wordpresss-interesting-way-of-dealing-with-magic-quotes/">WordPress&#8217;s…Interesting Way of Dealing with Magic Quotes</a></li>
<li><a href="http://www.webmaster-source.com/2012/08/14/gitlist-view-your-git-repositories-on-the-web/">GitList: View Your Git Repositories on the Web</a></li>
<li><a href="http://www.webmaster-source.com/2012/08/21/twitter-api-terms-revision-ignites-controversy/">Twitter API Terms Revision Ignites Controversy</a></li>
</ul>
<h3>September</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/09/04/6-articles-you-should-read-before-storing-users-passwords/">6 Articles You Should Read Before Storing Users’ Passwords</a></li>
<li><a href="http://www.webmaster-source.com/2012/09/11/ditching-godaddy-here-are-some-alternatives/">Ditching GoDaddy? Here Are Some Alternatives</a></li>
</ul>
<h3>October</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/10/10/mozilla-persona-single-sign-on-finally-done-right/">Mozilla Persona: Single Sign On Finally Done Right?</a></li>
<li><a href="http://www.webmaster-source.com/2012/10/17/proposed-secure-password-hashing-api-in-php-5-5/">Proposed Secure Password Hashing API in PHP 5.5</a></li>
<li><a href="http://www.webmaster-source.com/2012/10/20/adding-imgur-support-to-tweetbot-for-mac/">Adding Imgur Support to Tweetbot for Mac</a></li>
<li><a href="http://www.webmaster-source.com/2012/10/25/syntax-highlighting-in-mac-os-x-quick-look/">Syntax Highlighting in Mac OS X Quick Look</a></li>
</ul>
<h3>November</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/11/07/getting-more-from-twitter-bootstraps-typeahead-library/">Getting More From Twitter Bootstrap’s Typeahead Library</a></li>
<li><a href="http://www.webmaster-source.com/2012/11/14/fixing-slow-hosts-file-lookups-in-os-x-mountain-lion/">Fixing Slow Hosts File Lookups in OS X Mountain Lion</a></li>
<li><a href="http://www.webmaster-source.com/2012/11/21/automattic-releases-jetpack-2-0-featuring-the-new-photon-cdn/">Automattic Releases Jetpack 2.0, Featuring the New Photon CDN</a></li>
<li><a href="http://www.webmaster-source.com/2012/11/28/finderpath-extension-for-alfred/">FinderPath Extension for Alfred</a></li>
</ul>
<h3>December</h3>
<ul>
<li><a href="http://www.webmaster-source.com/2012/12/12/a-strange-and-sudden-design-trend/">A Strange and Sudden Design Trend</a></li>
<li><a href="http://www.webmaster-source.com/2012/12/19/scratchpad-write-html-and-watch-it-render-instantly/">Scratchpad: Write HTML and Watch it Render Instantly</a></li>
<li><a href="http://www.webmaster-source.com/2012/12/26/4-useful-curl-tricks/">4 Useful cURL Tricks</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://www.webmaster-source.com/2013/01/01/best-of-2012/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/


Served from: www.webmaster-source.com @ 2026-05-13 22:53:52 by W3 Total Cache
-->