Rails, Textile, and javascript WYSIWYG roundup

Plugins, Projects, Ruby on Rails 3 Comments »

If you allow rich text from your users in a Rails app, then you’re probably familiar with Textile. Either that or you’ve chosen the dark side, aka. Markdown. If that’s the case, I hate everything you stand for and I’ll bet you put your curly braces on the wrong line!

Assuming you’re one of The Chosen who has selected Textile as your input syntax of choice, you’ve probably got plenty of users who are turned off by the syntax. It may be easy for your average web developer to pick up yet another new syntax, but there are lots of people on the web who have never clicked the edit tab on Wikipedia, or think that links are specified with [URL=http://bbcode.com].

For these people, some sort of help is necessary. Quick tip sidebars, tutorials, and help pages only go so far. To make it truly useful you’ll probably have to dip into your Javascript bag of tricks. Luckily for you, a few others have already blazed that trail and created a handful of Textile utilities.


Textile Editor Helper (TEH)

NOTE: We’ve forked the Textile Editor Helper plugin to have more features and to conform to Rails 2.1 conventions. Our fork is available on github here:
http://github.com/felttippin/textile-editor-helper/tree/master

Textile Editor

The Textile Editor Helper is a very simple toolbar that sits at the top of your textareas, much like the Wikipedia toolbar. It provides many of the most basic Textile options, like bold and italics, plus some text alignment. Unfortunately, it doesn’t include linking and image includes, which are really easy to do with Textile.

Supposedly, you can add your own buttons, but I haven’t confirmed this. Plus, I think the whole plugin is based around the idea of prefixes/suffixes for text (like * for strong, or _ for em), so anything that requires more than that might not be possible. So, TEH is a good solution if all you need is some basic formatting help.

Live Textile Preview


The Live Textile Preview (aka SuperTextile) is simply a Javascript implementation of the Textile parser. So, you can convert Textile to HTML on the client side. This allows users to experiment with the syntax and quickly see what the changes will look like.

Unfortunately, from my cursory testing, it only implements most of the Textile syntax. Basic text changes, images, and links are covered. However, advanced text alignment and CSS styling elements seem to be beyond its capabilities. So, it’s not perfect. Still, if you only need the basics, SuperTextile can make life bearable for your users.

Sanskrit WYSIWYG editor

Sanskrit

Sanskrit is a true WYSIWYG editor, and the only one I’ve seen for Textile. However, it only does the absolute basics, so I can’t recommend it. Plus, I don’t think it’s a great idea to hide the raw Textile from your users. I’m a fan of the Wikipedia / Mediawiki way of things, where you provide some editing help, but your users are always looking at the raw text. Eventually, they’ll get the hang of things and won’t need the crutch of the editor buttons anymore.

markItUp!

markItUp! could be the most promising of all the solutions. A general purpose syntax parser written on top of jQuery, markItUp! can translate any syntax into HTML, provided you write the correct parser. Further, someone has already gone through the trouble and created a Textile parser!

I haven’t installed or tested markItUp!, but I was very impressed after playing around with the Textile demo. It seemed capable of most of the Textile syntax (including links and images), and even included a handy-dandy preview feature (you must render on the server side and return the HTML, I believe). So, it includes the best of all worlds: users work on raw Textile, but can get a live preview at the click of a button.

Update I finally got a chance to play with markItUp and it is hands down the best editor out of the bunch. Unless you need a true wysiwyg (in which case Sanskrit is the only one, AFAIK), then skip all the others and go straight to markItUp.

More?

Well, that’s all the Textile help I’ve found so far. Each one has its plusses and minuses, but any of them is probably better than a bare textarea with little or no help.

If I’ve left anything out, please let me know and I’ll add it to the list. With a little help, we can put together a comprehensive list of all the Textile tools available for Rails programmers.

Working in a literal sweatshop

Projects 1 Comment »

Our home air conditioning has been broken for the past few days, just as we have been pushing like crazy to get RioFlexPay up and running. To make matters worse, my development workstation is in our upstairs, which is a finished attic. Can you guess where all the heat in the house rises to? It routinely gets up to around 90F, and doesn’t cool off until late in the evening.

So, for the past two nights, I have been sitting at my desk, hacking away, as the sweat drips onto the keyboard. I guess it just shows what lengths you’ll go to when you really want to get something done.

Looking back, maybe I should have just gone for the more traditional startup location and put my workstation in my mom’s basement? Or, if TV is to be believed, I should be doing all my coding on a sexy new Mac while sipping gourmet coffee and listening to my tunes in the park. Um…no. Yet again, TV lies to me about the startup lifestyle. ;)

What about all of you? Where do you work? What horrors do you endure as you toil away late into the night?

Obsidian Portal – Now chock full of hCard and XFN

Obsidian Portal, Projects No Comments »
microformats

We’ve taken a small leap and added several microformats to Obsidian Portal. It was just so easy, there was no reason not to. For starters, we’re going with hCard and XFN.

Right from the start, we’re going whole-hog on hCard. I made a helper function to output an hCard every time we display a user’s avatar. So, every comment, every recent update, every friend link has an hCard on it. If the microformat-aware spiders cannot figure out who is who on Obsidian Portal, then they’re brain-dead.

Secondly, we’ve added XFN rels on the friend-links in the user’s profile. I don’t know of any (non-trivial) tools that are using XFN yet, but it’s easy enough to add, so we did. We’ve got rel=me on links to user’s other websites, and even self-referential rel=me links on the profile pages. We’re basically screaming “I am me” at the spiders.

Still on the TODO list is rel-tag for the NPC character tags. We’ve got a lot of plans for tags in the future, we just need to free up some time to work.

In the future, I might look at adding hAtom for the Adventure Logs, but honestly, we’ve already got RSS feeds, and I can’t see the value-add here. Am I missing something? Let me know.

Examples

Resources

  • Microformats.org – The definitive source for information.
  • Operator – A microformat parser plugin for Firefox. Adds a nice little toolbar that lights up when microformats are detected.
  • Tails Export – Another microformat parser plugin for Firefox. Seems to handle de-duping better than Operator.
  • rel-lint – A validator / checker for XFN and rel-tag

Build a crappy website, make a million dollars

Business, Projects 4 Comments »

I saw an article in the New York Times the other day about working 10 hours a week and making $10 million a year. The article profiles Markus Frind, who started an online dating website, Plenty of Fish. The main thrust of the article is that Markus barely works at all and just sits back raking in cash. Are there any other web entrepreneurs out there who are sick and tired of hearing this story over and over? This is all I ever hear, and I secretly dream about it while working on my projects, but it doesn’t match up well with the real world of late nights and no money.

Hmm, let’s look through the NY Times article and see what the keys are to creating a cash-cow website:

  • Just sit down and create a site as an experiment in teaching yourself a new programming language.
  • Ignore the interface and usability. If stuff looks bad, just say, “Users don’t care about that.”
  • Forget about customer service and moderation. Crowdsource it to the forums.
  • Don’t charge users for anything. Rely 100% on advertisements.
  • Lie in your hammock and collect checks.

Ok, I’ll admit, this is the life I want to live. This is the dream of all us web guys. However, I’m starting to suspect that the vast majority of “successful” web entrepreneurs invest a lot more effort and reap much smaller rewards. How many of us out there are pulling in $50, $100, or dare I say it, $500 a month from our projects? If I could get Obsidian Portal to generate $100 a month, I would be ecstatic. After paying off the hosting fees and whatnot, my take-home would probably be less then $1/hr. Still, it’s a goal to shoot for.

We can’t all be Digg, YouTube, or Facebook, but that’s OK. Success has different levels, and if we can just generate enough income to justify the amount of time we spend working on the sites we love, then that’s success. I just wish the media would profile a few more of us who live on the wrong side of profitability, work until 3:00 in the morning, and jump for joy with every subscription or CafePress T-shirt we sell.

Are you like me, barely scraping by (or not, as it were)? Drop a comment when you take a break from furiously writing code or begging someone not to cancel their account…

Update(Feb 2010) – We’re now making a decent amount of money from Obsidian Portal. Not enough to live on, but that goal is starting to become visible on the horizon. We’ve been at it for 3 years now, and maybe, maybe we’ll be ramen profitable in another 2-3. Still, from what I’ve seen of other web entrepreneurs, that’s a smashing success. So, to all you others out there in the same boat: It’s possible, but it’s slow and it’s damn hard.

Lonely Gamer Protocol

Lonely Gamer Protocol, Projects 3 Comments »

There are a handful of websites that have sprung up to help gamers find each other. It’s a great idea, and was one of our original motivations for creating Obsidian Portal. At the time, I didn’t know about the other player matching sites, and I was too scared to ask, thinking someone would steal my awesome idea. ;)

Unfortunately, most of these sites just don’t have the critical mass necessary to make them useful. I have signed up on a few, and I have never received any sort of response. Seeing as how I live in Atlanta, that’s a bad sign. If I can’t get matched up with players in a big city, there’s no way people in rural areas are getting any use out of it.

What if there were a way to combine and aggregate all the data from all the sites into a single index of gamers? In this day and age of web services and mashups, there is no reason that this should be impossible. So, for your consideration, I am proposing a communications protocol that will allow all the player matching sites to interoperate for the purpose of providing more results to their users. I am calling this the Lonely Gamer Protocol, or LGP.

Update 2007-11-06 I’m looking at using Google’s OpenSocial as a possible alternative to Atom. OpenSocial’s people element has almost all the necessary fields, and the gd:ExtendedProperty might be sufficient for the rest.

Motivations

Of course, the main motivation is to provide a better experience to our users. By sharing our data with each other, we will beef up the number of results returned to our users, thereby greatly increasing their chances of getting a hit.

However, at least in my case, there is a secondary, more commercial motivation. With Gleemax breaking onto the scene, Wizards of the Coast has become the 800 pound gorilla in the room that none of us small timers can compete with in terms of marketing or exposure. Unfortunately for the users, Gleemax just isn’t that great, at least not right now. They have a lot of promises, but very little in the way of actual features.

If we all try to compete directly with Gleemax, we will probably fail. They have an established userbase and a war chest they can dip into for advertising and paying their employees. However, if we band together and attempt to make interoperable services, we’ve got a shot. Pretty much any of the current gamer-finder sites is already 1000x better than Gleemax, and working together will only strengthen that lead.

Of course, Gleemax is free to support LGP as well, and this would be a great boon to the entire community. However, given its current state and their speed of resolving issues and feature requests, I don’t see this happening for a looong time. ;)

Goals

  • Free and open
  • Game and system neutral
  • Low barrier to adoption / easy to implement
  • Simple and lightweight
  • Language, culture, and country neutral

Please comment below if there are goals I should add or remove. Please note, however, that projects that are able to condense their goals down to a short list do better than ones that throw in everything and the kitchen sink.

Technical Specifications

LGP consists of a communication protocol along with a simple REST API for retrieving the data from participating providers.

Fields and Schema

The actual data involved in such an exchange should be very simple. Shooting from the hip, here are the fields I could come up with:

  • Player name
  • Geographic location (lat/lng)
  • Games interested in playing
  • Looking for game and/or Looking for players
  • Link to a profile page (w/ contact info)
  • Last update / login

XML is the obvious choice for the data exchange. That’s a no-brainer. Further, in order to further lower the barrier of entry, I suggest that we use a preexisting XML protocol as a base layer. Most of the fields I’ve suggested could be easily stuffed into an RSS or Atom feed.

LGP Field Atom Field Comments
Name title This would be the username, nickname, or campaign name
Geographic Location georss:point We can use the GeoRSS standard for Atom feeds to encode the user’s location. It would be encoded as a simple point element.
Preferred Games category Cram all the games you want to play in as category elements. For bonus points, we can define a closed vocabulary for the more popular games. Of course, this would be in addition to an open, free-tagging scheme.
Looking for game ?? A flag to indicate that a player is looking for a game to join.
Looking for players ?? A flag to indicate that an existing group or campaign is looking for more players.
Link to profile link This would be a link to a profile page for the user. Following this link would be the primary way of finding contact info for the player. Note: This link would probably also be used for the id field required by an Atom feed.
Last update / login updated This field indicates the last time the user updated their profile or logged in or something similar. The main goal is to let the stale entries settle to the bottom while the active, searching players can be easily found.

Looking back on that list, there are a few fields that need to be fleshed out and some formats need to be agreed upon, but the core functionality easily fits. Using Atom as the base for this protocol provides a lot of great benefits. As I mentioned before, most languages will have an Atom parser, making feed consumption that much easier. In addition, many will have tools to help construct feeds. Finally, it will be possible for the data to be made available to individual users, if they wish, just by subscribing with an Atom feed syndication tool. It might strip out some of the additional fields that we add, but if you provide filtering at the upstream level (ie. “Subscribe to a feed of all the gamers within 50 miles”) then it shouldn’t matter.

Query API

I’ll be the first to admit that I’m not really sure what’s required here. There needs to be a way to harvest the data from the individual sources. Further, there will need to be a way to filter the results, both in order to save on bandwidth, but also to make the results useful.

The following parameters allow for filtering based on set size, preffered games, and the last time a player’s profile was updated.

Parameter Required Comments
limit N The maximum number of entries to return. Defaults to something reasonable, like 100.
start N The index of the first record to receive. Manipulating start and limit allows a client to iterate through a result set. Defaults to 0.
categories N A comma separated list of categories. This allows for filtering based on which games a client is interested in.
last_update N A date field (what format does Atom use?) indicating that you only want results that have been updated after the specified date.

Filtering on geographic location would probably also be incredibly useful, but it’s not nearly as trivial as the previous parameters listed. Some tools make geocoding and “within X miles of Y” type searching very easy. Still, this would raise the barrier of entry. Perhaps it could be an optional filtering scheme that individual sites could implement, but was not required in order to be compliant with the protocol.

Issues

Adoption

Probably the largest hurdle to LGP would be getting the individual sites to share their data. For the larger sites, their userbase is their most valuable asset. Making it freely available might not seem in their best interests. However, it’s obvious that from the users’ perspective, LGP makes a lot of sense. Once the user data becomes a commodity, the sites will be forced to differentiate themselves based on their other features. For Obsidian Portal, that should be easy.

Still, joining up and sharing your data should generate a lot of traffic back to your site, and therefore signups or purchases or whatever else you count as a conversion. This is because the primary way of contacting a user will be through their profile page, which most likely exists on the site that provided the data. You could even require that someone sign up for your site before they can contact anyone, although that might be sort of a jerky thing to do.

Privacy

Everyone implementing LGP as a provider would need to make this very clear to their userbase and give them the ability to opt-out. In fact, perhaps opt-in would be a better policy, forcing users to specifically elect to be include. Still, why would they sign up on a player matching site in the first place unless they wanted to be found? I imagine most users would jump at the chance to be included.

The main issue with privacy that I can see is related to the geographic data that is passed with the feed. Giving out your address on the Internet is generally considered a Bad Thing, and this is no different. To that end, here are a few approaches.

First, you could restrict the lat/lng to a city area only. Therefore, you pass nothing more specific than a user’s city. The obvious downside is that for a city like New York there would be thousands of identically located entries. If you tried to map them, it would end up a mess, with all stacked one on top of the other.

Second, it might be possible to include an intentional error into the geographical data. Instead of feeding out the user’s exact coordinates, the system could give a random point within X miles of the user’s actual location. This would effectively mask their exact location, but would probably be very complicated to implement. Further, users would jump around on a map every time it was refreshed. Not a great solution.

Finally, the solution I propose is to pass the onus of anonymity on to the users. When asking them for address info, make it clear that they are not to enter their exact, home address. Instead, ask for nearby landmarks or street intersections. The Google Maps geocoding API is good enough to translate such strings into lat/lng coordinates. This would allow the users to accurately place their location, while at the same time assuring their anonymity.

Duplicate Entries

I am already signed up on multiple sites, and I imagine there are others as well. So, if all the data were aggregated, I would appear multiple times.

For now, we’ll punt on this issue from the LGP perspective. Individual consumers are free to try whatever de-duping mechanism they think will work best, or just forget about it. I imagine that even very dumb de-duping (ie. throw away all hits with the same name within 1 mile of each other) would be pretty good. Plus, unless people routinely sign up on 50 different sites, it won’t be a huge problem.

Ultimately, it would be nice to have a central registry that assigns unique identifiers, but trying to establish such a registry would probably be more work than it’s worth at this point.

Feedback

I’d love to hear feedback from anyone interested. Protocols like this only succeed if they achieve wide adoption and serve everyone’s needs. So, if I’m unfairly excluding someone, or I’ve missed something from the main list of goals, let me know in the comments. I will update this post over time as we come up with new ideas.

Throwing down the gauntlet

By no means is this document meant to be an academic discussion or pointless pontification. This is a very rough draft of what I hope will be an actual service that users can interact with very soon. So, I will go ahead and make a challenge to my fellow site owners: Let’s finalize a spec for LGP by December 2007, and have it implemented on our sites by Christmas (Dec 25th). If we could help our users find someone to game with over the break, it would be quite a present.

For my end, I solemnly swear to have Obsidian Portal implement at least the provider side within 2 weeks of the spec being finalized. I feel comfortable making this promise because I know just how easy it will be to do. Heck, it will probably take less than 3-4 hours to do the actual programming.

To any actual gamers reading this, you have a job too. Go back to the sites that you’ve registered on, post some links to this article, and demand that they support LGP. Tell them that by supporting and participating in the network, they will greatly enhance the user experience on their site. Believe me, once the users start demanding things, it gets very hard to ignore.

References

Tomorrow is BarCamp San Diego

BarCamp, Projects 1 Comment »

Tomorrow is Barcamp San Diego! It’s taken about a months worth of planning to get ready for tomorrow’s event and thanks to sponsors that we’ve lined out it’s going to be awesome.

BarCamp San Diego Logo

We’ve had almost 70+ people sign up so far and we’re expecting around 100+ people to show. Not to mention it’s been brought to my attention that we’ve been listed on Boing Boing as you can see below:

BarCamp San Diego on BoingBoing

BarCamp is an ad-hoc gathering born from the desire for people to share and learn in an open environment. It is an intense event with discussions, demos, and interaction from participants. The name BarCamp was inspired as a complement to FooCamp. FooCamp is the annual invitation only, no-structure, no plan, tent on the lawns, hacker event hosted by publisher Tim O’Reilly.

Two videos capture the essence of BarCamp. Take a look at video summaries from BarCamp SF and BarCamp Austin

Let the partying begin!

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in