<?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>Botsko.net - Web Development in Portland, Oregon</title>
	<atom:link href="http://www.botsko.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.botsko.net/blog</link>
	<description>continuing education</description>
	<lastBuildDate>Tue, 01 May 2012 22:16:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Announcing Snowy Evening &#8211; Bug and Issue Tracking for Clients &amp; Developers</title>
		<link>http://www.botsko.net/blog/2012/05/01/announcing-snowy-evening-bug-and-issue-tracking-for-clients-developers/</link>
		<comments>http://www.botsko.net/blog/2012/05/01/announcing-snowy-evening-bug-and-issue-tracking-for-clients-developers/#comments</comments>
		<pubDate>Tue, 01 May 2012 22:16:41 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=1000</guid>
		<description><![CDATA[After two and half years of work, we&#8217;re finally launching Snowy Evening. Head on over the announcement, or go signup for your free account now.]]></description>
			<content:encoded><![CDATA[<p>After two and half years of work, we&#8217;re finally launching Snowy Evening. Head on over the <a href="http://blog.snowy-evening.com/2012/05/01/introducing-snowy-evening/">announcement</a>, or go <a href="https://snowy-evening.com">signup for your free account now</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2012/05/01/announcing-snowy-evening-bug-and-issue-tracking-for-clients-developers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Journey to Launch: Ten Lessons from Launching Our Product, Snowy Evening</title>
		<link>http://www.botsko.net/blog/2012/04/27/journey-to-launch-ten-lessons-from-launching-our-product-snowy-evening/</link>
		<comments>http://www.botsko.net/blog/2012/04/27/journey-to-launch-ten-lessons-from-launching-our-product-snowy-evening/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 22:55:52 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[launch]]></category>
		<category><![CDATA[snowy]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=986</guid>
		<description><![CDATA[By Mike Botsko Kiwi It&#8217;s been an astounding six years since a web-designer friend and I began work on our first product. Our goal was to design a software-as-a-service product that would grow into a business which could support us both financially. We ran individual web design/development companies but often worked together, and had become [...]]]></description>
			<content:encoded><![CDATA[<p><em>By Mike Botsko<br />
</em><br />
<strong><em>Kiwi</em></strong></p>
<p>It&#8217;s been an astounding six years since a web-designer friend and I began work on our first product. Our goal was to design a software-as-a-service product that would grow into a business which could support us both financially. We ran individual web design/development companies but often worked together, and had become good friends very quickly. We took a product I had developed for myself and started a new version. It was codenamed <em>Kiwi</em>.</p>
<p>Kiwi came together quickly because of our excitement for what it represented: the possibility of having complete control over our product. Clients could never dictate what limitations we had to work around and there was no red-tape from legal and I.T. teams. After six months of highly motivated work it was stable enough to begin using internally, and shortly after we made agreements allowing local companies to use the service during development. Interested company contacts were piling up fast &#8211; from health insurance agencies to sports product manufacturers.</p>
<p>One woman even overheard us during a lunch meeting and was so interested she gave us her card. We we&#8217;re excited. We felt like we were in complete control. We had outlined a set of features that had to be present, and were perfectly clear to each other about what had to wait. </p>
<p>Soon we had too much client work &#8211; several large deadlines for some extremely demanding corporate clients drew our attention away. I&#8217;ll have to be honest and say my partner in this product began dropping the ball on his portion a lot more than I was, but I figured it was a temporary saturation of work.</p>
<p><strong>Lesson #1:</strong> <em>Don&#8217;t worry about losing focus on a side project. Your budding idea needs you to be your best, and if you&#8217;re putting in too many hours or neglecting paying-work, you&#8217;re going to suffer. If you return and can still feel as motivated about the idea, you know it&#8217;s the right project.</em></p>
<p>Six months went by before we were able to get back to our product. Meetings resumed, excitement levels came back, and we were sure launch day was approaching. However, I was still noticing delays from my partner that didn&#8217;t make sense to me. I thought <em>I&#8217;m able to get my work done and I&#8217;m working all day, teaching at night, and I have two kids as well, so why is he not getting his work done? His schedule is less busy than mine!</em></p>
<p>I&#8217;m the kind of guy that when I have a product I want to make, I run with it until it&#8217;s made. I may lose steam or take a break but my partner would go weeks without doing any work outside of the office. He&#8217;d just relax at home. Deadlines were being missed. I&#8217;d keep asking when tasks would be done, I&#8217;d ask if they could be done by a specific date and they rarely were. He was the best at what he did so I was too afraid to make an issue of out of it.</p>
<p><strong>Lesson #2:</strong> <em>You need to be open to your partners scheduling decisions as long as they can consistently keep up with the progress of others and make their deadlines.</em></p>
<p><strong>Lesson #3:</strong> <em>The moment you feel something isn&#8217;t working, bring it up. Don&#8217;t settle for something if you&#8217;re not happy.</em></p>
<p>We consulted with several investors for advice on getting funding to complete the project. We felt that this could be the solution to our lack-of-time issue. We ultimately decided that it wasn&#8217;t smart (thank god) but we did add three new members to our baby company.</p>
<p>Three former coworkers and friends of my partner came on board. I didn&#8217;t know them until just prior to their joining. They had once built a software company from the ground up, sold it for <em>lots</em> of money to a large corporation and had the experience, resources, and connections to help us create a spectacular company.</p>
<p>We all had mostly-weekly meetings in our office for a <em>year</em>. A lot of great ideas, a lot of debates that changed how we thought about our product and its potential.</p>
<p><strong>Lesson #4:</strong> <em>If anyone shows up at the next meeting having not done a single bit of work, and has no good excuse, it&#8217;s time to figure out why they&#8217;re on board.</em></p>
<p>I could have not wasted an entire year.</p>
<p>These guys were clearly smart, clearly experienced. They just weren&#8217;t right for <em>this</em> product. Two of them were programmers but had no experience programming for the web. They had no exposure to our target market and knew only what we told them about our competition. They all had other endeavors already and found it hard to focus much time and energy into the project. This delay was made worse when my partner entered another long period of time without a single minute of work. Six months, at least.</p>
<p>During this time I had completely re-written the core logic of the application based on a much-improved version of our internal framework. I spent time training the partners on the technology, setting up code access and emails, and doing a lot of organization work. I wrote a ton of &#8220;product direction documentation&#8221; which felt like busy work from elementary school. I&#8217;m sure 37Signals would agree.</p>
<p><strong>Lesson #5:</strong> <em>Adding super-smart, previously successful partners to your company is worthless if they&#8217;re not right for the market. You&#8217;ll get a year of generic business help and crazy white board diagrams but you&#8217;ll also have another year without a product.</em></p>
<p>Somehow we all stopped meeting and six months later I realized they had essentially ceased to exist. Not one email. In 2009, I requested that we drop the three individuals from our company and my partner agreed. I felt bad about the decision but it was clearly not working.</p>
<p><strong>Lesson #6:</strong> <em>As the founder, the business and the product is your first priority. Get rid of everything that honestly isn&#8217;t contributing to it.</em></p>
<p>We eventually stopped working on Kiwi because the market had become absolutely saturated with competition. So many products were encroaching on our territory that we felt less and less confident that we could make any money. Our ambition dropped to the lowest of lows.</p>
<p><strong><em>Snowy</em></strong></p>
<p>In October 2009 I made the decision to begin building a bug tracking application. I had long been complaining about the existing tools and finally had a light-bulb moment about why I should spend my time making a new one.</p>
<p>I already knew we could make a killer interface that was easy enough for clients to use but also powerful enough for us (developers). I already knew that I could eliminate the issues I had with existing tools. My realization was that I could build a product that allowed our deployed applications to report back errors rather than storing them locally, so that we could easily track those issues and be one-step ahead of our clients. </p>
<p>Whether or not this product would ever be used by others, it was going to be perfect for me.</p>
<p><strong>Lesson #7:</strong> <em>If you can&#8217;t actually use your own product, you&#8217;re not supposed to build it.</em></p>
<p>Work began. I was initially going to build the entire application myself to avoid the problems I had before. However I quickly realized that the interface could use the perfectionist&#8217;s touch, and I asked my partner from Kiwi if he would be willing to put together some designs for this issue tracker. He agreed. Six months later I had a lot of my work completed. The interface was moving along, but slower than I would have liked.</p>
<p>Soon it was mid-2010 and the effects of the recession were starting to hit us both. We were struggling with a long list of clients that suddenly couldn&#8217;t pay us, and new clients were nowhere in sight. I used some of my suddenly-free time to market for new work, &#8211; but the rest went into the new product. My partner did the opposite &#8211; he put in even less time on our product than he did when things were busy.</p>
<p>By 2011 I was fed-up with the lack of progress on the design. There was so little progress from my partner I assumed he was no longer interested. I began looking for a new designer and it wasn&#8217;t long before I had several candidates. A few weeks later I had narrowed it down to one.</p>
<p>I was excited about the new designer as I had heard of his work before, and he seemed extremely interested in the product. I emailed my partner with the news. </p>
<p>After several days of no response, I eventually got an email from my partner apologizing for the lack of focus and consistent problems with the project. He outlined ways we could get back on track and was trying to save our friendship. He asked for another chance. I decided that it was best to try to work this out and give it another shot. Not only did I think his work was unbeatable, but he was a good friend. </p>
<p>My choice was upsetting to the candidate I had selected. I should have, and could have handled that a lot better. </p>
<p><strong>Lesson #8:</strong> <em>Sometimes, saving the friendship means stopping the partnership before you truly wind up hating each other.</em></p>
<p>Like he promised, he recommitted to the work and after several months we had the product almost ready for a private beta. Despite having a sizable portion of the design work still incomplete, we decided to go ahead with a beta. We settled with a very ugly sales page and sent an email to a few hundred friends and coworkers. Things were looking up. Snowy was closer to launch than Kiwi had ever been.</p>
<p><strong>Lesson #9:</strong> <em>Nothing motivates you like seeing people use your product. It can be hard to see what doesn&#8217;t work but the amazing fact is that you have the power to fix it.</em></p>
<p>We both dealt with some personal issues that delayed us in the last half of 2011 but by early 2012 we were on our final stretch. Yet suddenly, we lost a few more months because my partner has become unavailable for the work. I ended up taking over the remaining bit of design work. I&#8217;ve been cranking away with final tweaks and testing and we&#8217;re finally ready to launch a product, two and half years after we started, and six and half years since we began this endeavor.</p>
<p>I&#8217;d like to introduce <a href="https://snowy-evening.com/">Snowy Evening</a>. An issue tracking application with an incredibly clean and easy to use interface, powerful features that blend seamlessly, and a lot more. </p>
<p>Built with determination, and run by a guy who&#8217;s truly invested in it&#8217;s survival. I&#8217;m in it for the long haul.</p>
<p><strong>Lesson #10:</strong> <em>Working with people who don&#8217;t share your work habits or ability to sit down and make progress is like swimming upstream. Do your best to find partners who truly match your personality. Like marriage you&#8217;ll always have differences but if you&#8217;re all driven and can manage themselves professionally, you can make it to product launch. That&#8217;s when the real journey begins.</em></p>
<p>As Snowy grows, I&#8217;ll continue posting here about the behind-the-scenes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2012/04/27/journey-to-launch-ten-lessons-from-launching-our-product-snowy-evening/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery Form Builder 0.4</title>
		<link>http://www.botsko.net/blog/2011/12/15/jquery-form-builder-0-4/</link>
		<comments>http://www.botsko.net/blog/2011/12/15/jquery-form-builder-0-4/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 20:07:58 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=982</guid>
		<description><![CDATA[I need to write an extension application on top of my popular jQuery Form Builder plugin so I finally took the time necessary to perform some long-wanted updates. The xml-based form loading system is finally gone, replaced by a pure JSON solution. There&#8217;s a lot more code cleanup, some bug fixes, and now some sample [...]]]></description>
			<content:encoded><![CDATA[<p>I need to write an extension application on top of my popular <a href="http://www.botsko.net/blog/2009/04/07/jquery-form-builder-plugin/">jQuery Form Builder</a> plugin so I finally took the time necessary to perform some long-wanted updates. The xml-based form loading system is finally gone, replaced by a pure JSON solution. There&#8217;s a lot more code cleanup, some bug fixes, and now some sample MySQL integration in addition to existing static data loading examples.</p>
<p>The extension layer I&#8217;m working on will add functionality for building basic quizzes and scoring them, and hopefully, some MongoDB support. When completed I&#8217;ll push that functionality as well. But for now, I need your help in testing the changes in 0.4.</p>
<p>As usual, <a href="https://github.com/botskonet/jquery.formbuilder">source code and downloads</a> are on GitHub.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/12/15/jquery-form-builder-0-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Opinion of SASS and LESS for CSS</title>
		<link>http://www.botsko.net/blog/2011/09/27/my-opinion-of-sass-and-less-for-css/</link>
		<comments>http://www.botsko.net/blog/2011/09/27/my-opinion-of-sass-and-less-for-css/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 19:27:14 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=976</guid>
		<description><![CDATA[I&#8217;ve been working with CSS for more than a decade and I know all too well the problem areas, primarily in browser support and development difficulties. Tools like Firebug and similar page inspectors have changed how I debug problems but as developers, we&#8217;re always seeking the more efficient route. On paper, the ideas behind Sass [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working with CSS for more than a decade and I know all too well the problem areas, primarily in browser support and development difficulties. Tools like Firebug and similar page inspectors have changed how I debug problems but as developers, we&#8217;re always seeking the more efficient route.</p>
<p>On paper, the ideas behind Sass and Less seem amazing. Shorten css development by using variables (for colors, etc), reduce the amount of written syntax by calling functions once, that when compiled, produce all necessary vendor prefix equivalents, and so on. By themselves, those were enough to convince me to try it.</p>
<p>I tried Less first, which is mainly different by the fact that it uses javascript to compile the real css. For those unwilling to add another script and process time to the client-side there are server-side solutions as well, and then there&#8217;s Sass. Sass has essentially the same features but is compiled on the server by Ruby gems.</p>
<p>However, when I began using these in already-live projects I discovered how painful they are. Here is a quick rundown of everything I&#8217;ve discovered about using these technologies versus hand-written CSS.</p>
<p><strong>The Environment</strong></p>
<p>Right out the gate, using Sass was a pain because I had absolutely no development environment for it. I had to install ruby, as well as the gems for compiling it. Firebug needs an additional plugin (and the gems need additional configuration) so that it will point you the Sass file and <em>not</em> the compiled css file. All of my editors/IDEs needed special plugins in order to recognize the syntax (for coloring, etc). </p>
<p>Now this is all install-once-and-you&#8217;re-set stuff but it still throws several additional steps into the mix when I move to new machines, etc.</p>
<p>Every day of work I need to ask the compiler to watch the project for changes. When I forget to do this, I get frustrated wondering where my css changes are.</p>
<p><strong>The Nesting Danger</strong></p>
<p>One of the benefits of sass/less is the ability to nest selectors. The sass could look like:</p>
<pre class="brush: css; title: ; notranslate">
body {
  /* ... styles ... */
  header {
    /* ... styles ... */
    nav {
      /* ... styles ... */
    }
  }
}
</pre>
<p>When compiled, the selector for <code>nav</code> becomes:</p>
<pre class="brush: css; title: ; notranslate">body header nav {  }</pre>
<p>The issue is that while attracting you with a nicer layout in the raw css file, it&#8217;s compelling you to build unnecessarily complex selectors. Although there are times when you need to specify the hierarchy, it&#8217;s not <em>every</em> time. In one project I&#8217;ve taken over, almost everything is nested this way.</p>
<p>It&#8217;s a performance hit to the browser because every chain becomes longer and requires a more specific application of the styles. The bigger issue is that it becomes an absolute nightmare trying to override styles. When I&#8217;m attempting to override a base style for a larger screen size I must repeat the entire selector because CSS requires that specificity.</p>
<p>So I&#8217;ve wound up writing selectors that look like the following:</p>
<pre class="brush: css; title: ; notranslate">body #main ul li a { float: none }</pre>
<p>It creates a lot more hassle about figuring out what the exact selector needs to be, debugging it when it&#8217;s not working, and sorting through the clutter this adds.</p>
<p><strong>Commit Spam</strong></p>
<p>When using version control it&#8217;s very easy to suddenly see a huge amount of commit spam from the compiled css. You can bypass this by compiling the css on deployment but that&#8217;s a bit more effort. If you have development configurations in place, sass will leave a lot of comments in the compiled css referencing the original location of the sass-version. These change with every compile and if you have a thousand-line-long css files, your commit diffs will be absolutely huge, even for a one-line change.</p>
<p>In fact reviewing said commits will be impossible because you can&#8217;t figure out what changed in all of that mess. In order to avoid that, you need to be sure that you never commit compiled code with any development/debug info left in.</p>
<p>When you&#8217;re working by yourself I see more of a benefit to using these technologies but when you&#8217;re working with a team, you&#8217;re not the only one who has to do these steps. It becomes the entire team.</p>
<p><strong>Conclusion</strong></p>
<p>I&#8217;m ready for you tell me why I&#8217;m wrong. But in the end I have to ask if all of this work is really worth not having to write extra vendor prefixes (which we all copy/pasted anyway) and having to refer back to your notes for each rgb/hsl/hex color code? It seems like that&#8217;s a lot easier to do to me. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/09/27/my-opinion-of-sass-and-less-for-css/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Web Hosted Bug and Issue Tracking</title>
		<link>http://www.botsko.net/blog/2011/06/11/web-hosted-bug-and-issue-tracking/</link>
		<comments>http://www.botsko.net/blog/2011/06/11/web-hosted-bug-and-issue-tracking/#comments</comments>
		<pubDate>Sat, 11 Jun 2011 16:17:15 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bugzilla]]></category>
		<category><![CDATA[issue tracking]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[snowy]]></category>
		<category><![CDATA[trellis]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=970</guid>
		<description><![CDATA[I&#8217;ve never been satisfied with issue tracking software. It essentially boils down to the fact that developers seem to sacrifice a clean design and usable product for features or vice versa &#8211; the tools our clients would find usable were never the same tools that the developers and designers could find usable. This will never [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve never been satisfied with issue tracking software. It essentially boils down to the fact that developers seem to sacrifice a clean design and usable product for features or vice versa &#8211; the tools our clients would find usable were never the same tools that the developers and designers could find usable.</p>
<p>This will never be a problem again, thanks to Snowy Evening. Snowy-Evening.com has been in development for almost two years and despite an amazing list of features (all listed on the home page) it has an incredibly clean and very easy to understand design. Our clients have been using it for a year and there are several well known web companies already using it for their projects.</p>
<p>I highly recommend you try a free account at <a href="https://snowy-evening.com/">Snowy Evening</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/06/11/web-hosted-bug-and-issue-tracking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sizing Text to Container with jQuery ExpandText</title>
		<link>http://www.botsko.net/blog/2011/05/23/sizing-text-to-container-with-jquery-expandtext/</link>
		<comments>http://www.botsko.net/blog/2011/05/23/sizing-text-to-container-with-jquery-expandtext/#comments</comments>
		<pubDate>Tue, 24 May 2011 04:48:35 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[expandtext]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=958</guid>
		<description><![CDATA[A frequent problem with text on the web is that there&#8217;s no way to automatically adjust the font size based on the dimensions of it&#8217;s containing element &#8211; at least in a way that changes size when the container does. There are a few plugins that automatically size the text (like FitText) but they only [...]]]></description>
			<content:encoded><![CDATA[<p>A frequent problem with text on the web is that there&#8217;s no way to automatically adjust the font size based on the dimensions of it&#8217;s containing element &#8211; at least in a way that changes size when the container does.</p>
<p><span id="more-958"></span></p>
<p>There are a few plugins that automatically size the text (like <a href="http://fittextjs.com/">FitText</a>) but they only increase the font size, and the font sizes don&#8217;t adjust when the parent is adjusted.</p>
<p>Enter my newest plugin <a href="https://github.com/botskonet/jquery.expandtext">ExpandText</a>. You can provide a minimum and maximum font size and the plugin will adjust the font when the container element changes dimensions. It uses the width and height of an auto-inserted <code>span</code> which wraps the text directly.</p>
<p>Simply attach the plugin to the text element selector inside of a document ready and window resize:</p>
<pre class="brush: jscript; title: ; notranslate">$(function(){
	$(window).resize(function(){
		$('.text').expandText();
	}).trigger('resize');
});</pre>
<p>The benefit of the <code>span</code> technique is that we can avoid trying to measure the characters themselves which change dramatically with each font type and style.</p>
<p><a href="https://github.com/botskonet/jquery.expandtext">Download the code via GitHub</a> and <a href="http://experiments.botsko.net/tests/jquery.expandtext/">try out the demo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/05/23/sizing-text-to-container-with-jquery-expandtext/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Sphinx Search Server</title>
		<link>http://www.botsko.net/blog/2011/05/07/installing-sphinx-search-server/</link>
		<comments>http://www.botsko.net/blog/2011/05/07/installing-sphinx-search-server/#comments</comments>
		<pubDate>Sun, 08 May 2011 04:34:38 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[installing]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=741</guid>
		<description><![CDATA[I&#8217;ve always used MySQL fulltext indexes with a match query for keyword searches but I&#8217;ve never been happy with the results and lack of configuration choices. The limited nature of word interpretation and the boolean searches were useless when visitors didn&#8217;t know how to use search operators. Fulltext indexes require the MyISAM table structure &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always used MySQL <code>fulltext</code> indexes with a <code>match</code> query for keyword searches but I&#8217;ve never been happy with the results and lack of configuration choices. The limited nature of word interpretation and the boolean searches were useless when visitors didn&#8217;t know how to use search operators. Fulltext indexes require the MyISAM table structure &#8211; yet we generally prefer InnoDB because of performance and foreign key constraints.</p>
<p>For a recent project I decided to finally (long overdue, I know) make the the transition to an external search and indexing application called <a href="http://sphinxsearch.com/">Sphinx</a>.</p>
<p><span id="more-741"></span></p>
<p>Sphinx is a separate server that will index content from a variety of sources (in our case, MySQL) and provides an API that allows you to search the content more effectively.</p>
<p>If you&#8217;re using it with MySQL, you need to ensure that the <code>mysql-devel</code> package has been installed. Since this project was on CentOS, this is a simple yum call:</p>
<pre class="brush: bash; title: ; notranslate">$ yum mysql-devel</pre>
<p>Once that&#8217;s installed you&#8217;re ready to install Sphinx:</p>
<pre class="brush: bash; title: ; notranslate">$ wget http://sphinxsearch.com/files/sphinx-1.10-beta.tar.gz
$ tar xzvf sphinx-1.10-beta.tar.gz
$ cd sphinx*
$ ./configure --prefix=/usr/local/sphinx
$ make
$ make install
$ sudo mkdir -p /var/data/sphinx</pre>
<p>Once installed, you need to create a configuration file that will dictate where the data is indexed from, and how the search server will behave.</p>
<pre class="brush: bash; title: ; notranslate">$ vi /usr/local/etc/sphinx.conf</pre>
<p>Sphinx needs to know about two things &#8211; where to find the data for indexing, and how to index it. The <code>source</code> needs to point to a database or content source &#8211; in this case it points to our MySQL database.</p>
<pre class="brush: bash; title: ; notranslate">
source name_your_source
{
    type                            = mysql
    sql_host                        = 127.0.0.1
    sql_user                        = mysql_user
    sql_pass                        = mysql_pass
    sql_db                          = mysql_database
    sql_sock                        = /var/run/mysqld/mysqld.sock
    sql_port                        = 3306

    # indexer query
    # document_id MUST be the very first field
    # document_id MUST be positive (non-zero, non-negative)
    # document_id MUST fit into 32 bits
    # document_id MUST be unique
    sql_query = SELECT id, field1, field2 FROM ourtable;

    # document info query
    # ONLY used by search utility to display document information
    # MUST be able to fetch document info by its id, therefore
    # MUST contain '$id' macro
    sql_query_info  = SELECT * FROM ourtable WHERE id=$id
}
index name_your_index
{
    source                  = name_your_source
    path                    = /var/data/sphinx/name_your_source
    morphology              = stem_en
    min_word_len            = 3
    min_prefix_len          = 0
#    min_infix_len           = 3
}
searchd
{
	port				= 3312
	log					= /var/log/searchd/searchd.log
	query_log			= /var/log/searchd/query.log
	pid_file			= /var/log/searchd/searchd.pid
}
</pre>
<p>The first few lines clearly setup the database connection credentials. The <code>sql_query</code> statement is what pulls in the data for indexing. Everything you need indexed needs to be pulled with this query. It&#8217;s also possible to pull fields that won&#8217;t be indexed, but will actually be used for filtering the data. These are called <a href="http://sphinxsearch.com/docs/1.10/attributes.html">attributes</a>.</p>
<p>The <code>index</code> component configures the index itself and how searches will be processed. Features like the minimum word length, and morphology (how variations of the word are matched) are defined here.</p>
<p>The <code>searchd</code> component simply sets some configurations for the daemon itself.</p>
<p>Once configured, run the following command and Sphinx will build all of the indexes:</p>
<pre class="brush: bash; title: ; notranslate">$ /usr/local/sphinx/bin/indexer --config /usr/local/etc/sphinx.conf --all </pre>
<p>If the configuration file is loaded properly and the database connection/queries work, you will see the indexer output:</p>
<pre class="brush: bash; title: ; notranslate">using config file '/usr/local/etc/sphinx.conf'...
indexing index 'yournamedindex'...
collected 1421 docs, 0.1 MB
sorted 0.0 Mhits, 100.0% done
total 1421 docs, 75457 bytes
total 0.188 sec, 400587 bytes/sec, 7543.82 docs/sec
total 2 reads, 0.000 sec, 22.6 kb/call avg, 0.0 msec/call avg
total 6 writes, 0.000 sec, 17.1 kb/call avg, 0.0 msec/call avg</pre>
<p>Once the index is complete, you can run a test search directly without starting the daemon:</p>
<pre class="brush: bash; title: ; notranslate">/usr/local/sphinx/bin/search --config /usr/local/etc/sphinx.conf searchtermhere</pre>
<p>You will see a dump of every matching document. Once you&#8217;ve got the search running, it&#8217;s time to start the daemon. First, we need to create a directory for the log files we asked for in the config:</p>
<pre class="brush: bash; title: ; notranslate">sudo mkdir -p /var/log/searchd</pre>
<p>Then, start the daemon:</p>
<pre class="brush: bash; title: ; notranslate">/usr/local/sphinx/bin/searchd --config /usr/local/etc/sphinx.conf</pre>
<p>Keep watching for more posts &#8211; I&#8217;ll discuss how to to work with the search from PHP, how to run incremental index updates, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/05/07/installing-sphinx-search-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git Push/Pull Alias Functions</title>
		<link>http://www.botsko.net/blog/2011/05/07/git-pushpull-alias-functions/</link>
		<comments>http://www.botsko.net/blog/2011/05/07/git-pushpull-alias-functions/#comments</comments>
		<pubDate>Sat, 07 May 2011 23:42:35 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=929</guid>
		<description><![CDATA[I&#8217;ve been using Git for just over two years now. It&#8217;s one of the few systems left that doesn&#8217;t have a graphical user interface I prefer. In the past years, many choices have either been launched or announced but I&#8217;m still a command-line only person. I grew tired of typing the full push/pull commands so [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Git for just over two years now. It&#8217;s one of the few systems left that doesn&#8217;t have a graphical user interface I prefer. In the past years, many choices have either been launched or announced but I&#8217;m still a command-line only person.</p>
<p>I grew tired of typing the full push/pull commands so I&#8217;ve finally spent some time searching for the best bash function on the net&#8230; which appears to be <a href="http://forrst.com/posts/My_gitstuff_bash_shortcuts_for_working_with_g-BwI">http://forrst.com/posts/My_gitstuff_bash_shortcuts_for_working_with_g-BwI</a></p>
<p>Edit your bash profile and place the &#8220;gpush&#8221; and &#8220;gpull&#8221; functions after anything that currently exists. I personally didn&#8217;t use the aliases shown in the pasted code sample, as I already use a different set.</p>
<pre class="brush: bash; title: ; notranslate">vi ~/.bash_profile</pre>
<p>When running <code>gpush</code> or <code>gpull</code> they will activate the associated commands on the current branch.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/05/07/git-pushpull-alias-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Best &amp; The Essential WordPress Plugins</title>
		<link>http://www.botsko.net/blog/2011/04/30/the-best-the-essential-wordpress-plugins/</link>
		<comments>http://www.botsko.net/blog/2011/04/30/the-best-the-essential-wordpress-plugins/#comments</comments>
		<pubDate>Sun, 01 May 2011 05:17:11 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[essential]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=911</guid>
		<description><![CDATA[I&#8217;ve worked with WordPress for at least six years now &#8211; on both personal and client projects. As a company we&#8217;ve been focusing on larger custom-built projects in the past few years so staying current in the WP community has been a lot more difficult. Because of this, I&#8217;m transitioning the WordPress courses to a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve worked with WordPress for at least six years now &#8211; on both personal and client projects. As a company we&#8217;ve been focusing on larger custom-built projects in the past few years so staying current in the WP community has been a lot more difficult.</p>
<p>Because of this, I&#8217;m transitioning the WordPress courses to a new instructor so that I can focus on my series of web development courses (which are my primary focus anyway). Before I put the materials I&#8217;ve developed for the WordPress courses into eternal digital storage I thought it would be best for me to share the list of tips and plugins used or mentioned in any of these courses.</p>
<p><span id="more-911"></span>I&#8217;d love your comments or recommendations on any plugins I&#8217;ve missed.</p>
<p><strong>Essential Plugins &#8211; For Every WP Install<br />
</strong></p>
<ol>
<li><a href="http://wordpress.org/extend/plugins/wp-db-backup/">WP-DB-Backup</a> &#8211; You can always re-download WordPress, and you&#8217;ll most likely be able to find your theme again. But you don&#8217;t have any backups of your database, which is the most important part. Install this plugin and schedule a backup so that if something happens, your <em>content</em> is still safe.</li>
<li><a href="http://wordpress.org/extend/plugins/google-sitemap-generator/">Google XML Sitemaps</a> &#8211; An XML-based sitemap is simply a directory of every page, post, and other information that search engines should be immediately aware of. It&#8217;s an amazing plugin working with an awesome standard  &#8211; and it&#8217;s done wonders for SEO on every website.</li>
<li><a href="http://akismet.com/">Akismet</a> &#8211; It even comes with WP. Comment spam is bad, and annoying but Akismet will handle it all for you. Free for personal use, with a small recurring fee for commercial.</li>
<li><a href="http://wordpress.org/extend/plugins/all-in-one-seo-pack/">All in One SEO Pack</a> &#8211; This tool modifies some basic functionality so that you can improve your search engine indexing. By making minor changes to the page titles, and meta information, your content is better suited for spidering.</li>
<li><a href="http://wordpress.org/extend/plugins/w3-total-cache/">W3 Total Cache</a> &#8211; WordPress isn&#8217;t exactly the fastest the piece of software, and with enough incoming traffic (usually unexpected traffic when someone popular links to you) it can quickly consume your server resources. The total cache plugin has a huge number of options that all help speed everything up. As the name implies, it caches page content so that php and apache aren&#8217;t churning as hard with <em>every single request</em>. Some great options for css, javascript, and html compression as well. Speed is worth every penny.</li>
</ol>
<p><strong>Statistics Plugins</strong></p>
<ol>
<li><a href="http://ronaldheft.com/code/analyticator/">Google Analyticator</a> &#8211; Google Analytics is the current leader in website statistic software. Even though adding the necessary javascript to your theme isn&#8217;t difficult, it&#8217;s still a pain especially if you&#8217;re not familiar with FTP software. Plugins like Analyticator insert the code for you, no matter the theme.</li>
<li><a href="http://wordpress.org/extend/plugins/clicky/">GetClicky</a> &#8211; Google Analytics is the leader, but I don&#8217;t see that lasting forever with the rise of real-time analytics tools. Clicky is pretty neat service and in many cases, better suited for clients who a) have small sites, b) want real-time information, and c) find G.A. too complex to work with.</li>
<li><a href="http://wordpress.org/extend/plugins/feedburner-plugin/">Feedburner</a> &#8211; The analytics tools are great, but they typically fall short when determining who&#8217;s subscribed to the RSS feeds of your website. If you have your feeds routed through <a href="http://www.feedburner.com">FeedBurner.com</a>, they can.</li>
</ol>
<p><strong>Social Media Integration</strong></p>
<ol>
<li><a href="http://wordpress.org/extend/plugins/twitter-widget-pro/">Twitter Widget Pro</a> &#8211; This plugin ads a widget (requires themes with widget support) that will display your last <em>x</em> tweets.</li>
<li>Facebook &#8211; There are so many plugins now for Facebook, and so many for posting info as well as reading, I&#8217;d recommend just browsing the <a href="http://wordpress.org/extend/plugins/tags/facebook">Facebook Plugin directory</a>.</li>
<li><a href="http://wordpress.org/extend/plugins/facebook-comments-for-wordpress/">Facebook Comments</a> &#8211; This plugin uses the Facebook comments API to load their commenting system onto your posts. Users with Facebook accounts can immediately discuss your post without messing around with the WordPress name/email and spam protection system.</li>
<li><a href="http://alexking.org/projects/wordpress">ShareThis</a> &#8211; Personally I despise seeing tools like these on a website, but they are still in high demand. ShareThis and a few similar plugins allow users to share your content on dozens of social networking websites. A range of icons and logos are displayed and the users choose which network to &#8220;share this&#8221; on.</li>
</ol>
<p><strong>Contact</strong></p>
<ol>
<li><a href="http://wordpress.org/extend/plugins/replyme/">ReplyMe</a> &#8211; This plugin will send an email to users when a comment they&#8217;ve made has been replied directly to. If you need more control, and you need to let them opt-in to such a service, <a href="http://wordpress.org/extend/plugins/subscribe-to-comments/">Subscribe to Comments</a> may work better.</li>
<li><a href="http://contactform7.com/">ContactForm7</a> &#8211; By far the most popular contact form builder. Before this plugin showed up in the repository, developers were essentially building such forms manually &#8211; whether they were directly in theme or wrapped inside of custom plugins. ContactForm7 is now the leader and offers a lot more than just basic contact form support.</li>
<li><a href="http://www.campaignmonitor.com/downloads/wordpress-contact-form-7-plugin/">Contact Form 7 Campaign Monitor Addon</a> &#8211; There are many popular email campaign services out there &#8211; MailChimp, Constant Contact, etc. They all have some basic WordPress plugins. Campaign Monitor is one of the most popular, but it&#8217;s even easier to setup because of this plugin which is simply an addon to ContactForm7.</li>
</ol>
<p><strong>Other</strong></p>
<ol>
<li><a href="http://www.bravenewcode.com/store/plugins/wptouch-pro/">WP Touch</a> &#8211; If your WordPress theme doesn&#8217;t have any mobile device support, WP Touch and WP Touch Pro are cheaper alternatives. These plugins create mobile-friendly versions of your content (independent of your theme however).</li>
<li><a href="http://wordpress.org/extend/plugins/syntaxhighlighter/">Syntax Highlighter Evolved</a> &#8211; For those of you who need the ability to display code snippets in your posts (like us) then you need this plugin. By providing a series of WordPress shortcodes, you can add proper syntax highlighting, line numbering, and the ability to copy the entire snippet to any block of code. Even better is the fact that it works in the comments too!</li>
<li><a href="http://wordpress.org/extend/plugins/yet-another-related-posts-plugin/">Yet Another Related Posts Plugin</a> (Related Entries) &#8211; There are several plugins that attempt to automatically link related posts, but this one seems to work out the best when properly configured. Still, changing the title of the link lists to &#8220;Possibly related&#8221; gives you a lot more leeway when things go wrong.</li>
<li><a href="http://wordpress.org/extend/plugins/mappress-google-maps-for-wordpress/">MapPress</a> &#8211; I&#8217;ve spent a lot of time working with the Google Maps API, so being able to add in a simple map directly from the posts page is extremely helpful. The free version has all of the important features but the pro version adds some more advanced functionality. Now that Google doesn&#8217;t require an API key, it&#8217;s even easier.</li>
</ol>
<p><strong>Resources</strong></p>
<ol>
<li><a href="http://codex.wordpress.org/Main_Page">The WordPress documentation</a>.<strong></strong></li>
<li><a href="http://www.wpbeginner.com/">http://www.wpbeginner.com/</a></li>
<li><a href="http://www.wp-tutorials.org/">http://www.wp-tutorials.org/</a></li>
<li><a href="http://wordpress.tv/">http://wordpress.tv/</a></li>
</ol>
<p>I&#8217;m sure there are hundreds of useful plugins that I haven&#8217;t listed. I&#8217;m always interested in trying out new plugins, so feel free to post any suggestions in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/04/30/the-best-the-essential-wordpress-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing a Snippets Library through Dropbox</title>
		<link>http://www.botsko.net/blog/2011/04/30/sharing-a-snippets-library-through-dropbox/</link>
		<comments>http://www.botsko.net/blog/2011/04/30/sharing-a-snippets-library-through-dropbox/#comments</comments>
		<pubDate>Sun, 01 May 2011 00:17:39 +0000</pubDate>
		<dc:creator>Michael Botsko</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[1password]]></category>
		<category><![CDATA[dropbox]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://www.botsko.net/blog/?p=914</guid>
		<description><![CDATA[I&#8217;ve been using the Mac application Snippets and it&#8217;s been getting better with each new release. One essential feature that&#8217;s still missing is any support for syncing a library through a service other than MobileMe. I&#8217;ve even contacted them about the issue, as many have. However, I&#8217;ve recently learned that there is a way to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using the Mac application <a href="http://www.snippetsapp.com/">Snippets</a> and it&#8217;s been getting better with each new release. One essential feature that&#8217;s still missing is any support for syncing a library through a service other than MobileMe. I&#8217;ve even contacted them about the issue, as many have.</p>
<p>However, I&#8217;ve recently learned that there is a way to <em>share</em> the library using <a href="http://www.dropbox.com/">Dropbox</a> &#8211; not <em>sync</em> it, but share it. Simply move the library itself. I had considered this option before (since it&#8217;s how I use <a href="http://agilewebsolutions.com/onepassword">1Password</a>) but there seemed to be no way to move the Snippets library.</p>
<p><span id="more-914"></span>The last item on their FAQ however, describes what we need:</p>
<ol>
<li>Copy the library from ~/Library/Application  Support/Snippets/Snippets.xml to your Dropbox account. (~ = Your user folder.)</li>
<li>Launch the application while holding the <code>option</code> key.</li>
<li>Click the &#8220;Choose a library&#8221; button, and select the new xml file in your Dropbox folder.</li>
</ol>
<p>You&#8217;re done! You can now use this same library from any of your machines with access to the same Dropbox folder.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.botsko.net/blog/2011/04/30/sharing-a-snippets-library-through-dropbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

