Snippets.sugar for Espresso

I’ve always been intrigued by the concept of a program for storing code snippets, but I’ve never found one that I could put to any practical use. I inevitably would end up storing a few snippets in it, and then abandoning it for my text editor’s built-in snippet management because it introduced too many extra steps when it came to inserting snippets as I code. External snippets managers had some very real benefits, but none that outweighed the usefulness of tab completions and tab stops.

Fortunately, I think I finally have a snippet manager that will work for me. Snippets.app 1.1.1 offers a unique new feature: a bridge API that allows third party applications to invoke the Snippets search panel or global menu and then do whatever they need to do with the user’s selected snippet. While they were working on the feature, Lucky Ants asked me if I’d like to help them show it off, so I collaborated with them to develop the Snippets.sugar for Espresso (download it here).

In case you don’t have a clear idea of why this is awesome, here’s what you can do with it:

  1. Once the Sugar is installed, choose Actions→Snippets.app→Insert Snippet (control-S) while editing a document in Espresso to jump to the Snippets search panel (or global menu)
  2. Find the snippet you want to insert, and hit enter
  3. The snippet will be inserted into Espresso, and any placeholders in the snippet will be converted into tab stops

It’s that last feature that vastly improves Snippets.app’s usefulness. Previously, snippets managers were basically just cut and paste. With Snippets.sugar’s integration into the core application’s APIs, though, you can leverage the full power of Espresso’s text snippet syntax.

That’s fun, but it gets better:

  • Your snippet can contain Snippets.app-style named placeholders or Espresso/Textmate-style numbered placeholders and they’ll automatically be converted into tab stops
  • Your snippet can contain Espresso or Textmate special variables like $EDITOR_PATH or $TM_SELECTED_TEXT, allowing your snippet to interact with your selected code, prefill the path to the document, and so forth
  • Because it’s an Espresso snippet, you can also use interpolated shell code, placeholder mirrors and transformations, etc.
  • When inserting a snippet that doesn’t contain any placeholders, it will be inserted as plain text, so you won’t have to worry about losing special characters like $ that sometimes get messed up in Espresso snippets

Additionally, you can move in the other direction. Just select some text in Espresso and choose Actions→Snippets.app→New Snippet (control-shift-S) to create a new snippet in Snippets.app using the selected text.

To choose whether to use the search panel or the global menu, open up the Espresso preferences, switch to the Advanced pane, and make sure that Snippets.sugar is selected in the dropdown at the top. There you’ll be able to choose what interface you like, force the Sugar to always use a particular type of snippet logic (if that’s necessary for some reason), and set some defaults for when you’re creating new snippets:

Snippets.sugar Preferences

Although this is a fantastic feature, you’ll still need to weigh up some pros and cons before you jump straight into it. On the positive side, it’s now feasible with Snippets.app to have a single, well-organized snippet library that includes advanced tab stopped snippets and can be shared across multiple text editors (for instance, this would make it a breeze to migrate a Textmate snippet collection for use with Espresso). Thanks to Snippets.app’s synchronization capabilities, you could also use your snippets collection across multiple computers far more easily than when Espresso’s snippet management features.

The main downside is that although the Snippets.sugar integrates Espreso and Snippets.app far more closely than before, it still is not a seamless integration because Espresso doesn’t know anything about the snippets until you select them. This means that you can’t use tab completions to trigger snippets, so the process of selecting the snippet you want to use is still relatively time consuming compared to using native snippets.

For more information about the other goodies available in Snippets.app 1.1.1, see the 1.1.1 blog announcement. I hope you enjoy Snippets.sugar!

Implementing scene fades in WebOS

I had a heck of a time implementing a simple scene fade (or “scroll fades” as they’re also called) in TapNote, mainly thanks to the lack of good information surrounding them. Most folks in the Palm forums recommend looking at the Style Matters example project, but Style Matters was apparently coded by someone who also believed that Coding Style Doesn’t Matter, so screw that.

Sadly, scene fades are only provided for free with some elements (the command menu, for instance), so most of the time you have to implement them by hand.

To get your scene fades up and running, you’ll need to stick a little extra HTML in your scene, add a CSS snippet to your stylesheet, and copy the image resources into your app.

HTML

The HTML is very straight-forward. Just stick this at the very bottom of your scene (don’t nest it in anything):

<div class="scene-fade bottom" x-mojo-scroll-fade="bottom"></div>
<div class="scene-fade top" x-mojo-scroll-fade="top"></div>

Obviously, if you only wanted a top or bottom fade, you’d only include one or the other.

CSS

This CSS snippet is a vastly condensed and improved version of the CSS used by the Style Matters program. Note that you’ll probably need to set height: 100% on your HTML and body elements because otherwise the absolute positioning of the scene fades might not work. If you do so and you’re still not having your bottom scene fade positioned properly, try additionally setting height: 100% on the wrapper element for your scene.

html, body {
    height: 100%;
}

/* === Scene Fades === */

.scene-fade {
    height: 54px;
    width: 100%;
    position: fixed;
    left: 0px;
    z-index: 100000;
    -webkit-palm-mouse-target: ignore;
}

.scene-fade.top {
    top: 0px;
    background: url(../images/fade-top.png) repeat-x center bottom;
}

.scene-fade.bottom {
    bottom: 0px;
    background: url(../images/fade-bottom.png) repeat-x center bottom;
}

Images

The images you need are squirreled away in the WebOS SDK. For instance, the ones I ended up using were located in this folder:

PalmSDK/0.1/share/samplecode/stylematters/images/

And were called my-scene-fade-bottom.png and my-scene-fade-top.png.

If locating those images is too much effort, though, you can just download the example code.

Finally, you will of course need to drop the images into your root images folder, and adjust the path to them in the CSS if it’s located more than a single level away from the project root. Enjoy!

TouchNote is now TapNote

Although I hadn’t expected to have an issue with TouchNote.com, they evidently didn’t like my use of the word “TouchNote” (despite using it for a completely different purpose on a platform they don’t appear to have any interest in) and rather than ask nicely had their lawyers threaten me with a trademark lawsuit.

Thanks, guys. It’s always a pleasure to interact with people who skip that whole tedious friendly request stage and go straight to threats.

In any case, I don’t have the resources for a legal battle (and would not have used the name in the first place if I thought they’d have a problem with it), so my app is now named TapNote.

The name change is going to take a couple of days to percolate through Palm’s system, but TapNote v1.1 should be in the app catalog probably Friday or Monday, depending on Palm’s turnaround.

Data model design in WebOS

When I was first starting to program TapNote I did a lot of reading through Palm’s documentation and other WebOS developer help sites, but I never was able to find any good information on how to set up a data model.

Turns out that there aren’t any official recommendations. Palm mentions the app/models folder mainly just to get you thinking about using an MVC design for your app, I suspect.

While I designed the architecture of my app, however, I thought a fair amount about how to break down the logic, and I ended up coming up with some guidelines that may help other developers with their app design. Of course, this is probably pretty obvious stuff for people who design with MVC regularly, but I would have found it useful when I was starting out with WebOS programming (particularly because it was complicated by WebOS’s persistently asynchronous nature).

Knowledge and responsibilities

The controller (or assistant, in WebOS parlance) knows these things:

  • The interface for the model
  • The expected Javascript object schema for the data
  • Details about the view elements (views being the HTML files for the scene)

The controller’s responsibilities are:

  • Querying the model for new data when needed
  • Updating view items with data once the model sends it over

The model (which should be either a Prototype class or a unique object stored in your app/models directory) knows these things:

  • Exactly what storage system is being used for the data
  • How to interact with the storage system (SQL queries or whatever else)
  • The Javascript object schema for the data

The model’s responsibilities are:

  • Gathering data when it is requested
  • Transforming the data from its raw format into the proper Javascript object
  • Returning the data using the provided callback

A decent metaphor is that of two coworkers in neighboring cubicles. The controller asks for something from the model, and tells it where to send the results. The model does what it needs to do to gather those results, then sends them where the controller requested. Neither can see into the other’s cubicle to know what exactly what their coworker is doing, but neither one needs to. Either model or controller can change what they’re doing with the data (how it’s stored or how it’s displayed), but this won’t affect their relationship to one another.

If you ever have something in the controller that depends on knowing what type of storage system is used for the data, you are doing it wrong. Similarly, if you ever have anything in the model that references or needs to know about specifically what view items are being populated with data, you need to rethink your architecture.

Basic layout

Unlike assistants which are automatically loaded by Mojo when their scene is pushed, you will need to add your model class to your app’s sources.json file by hand:

[
    {"source": "app/models/myDataModel.js"},
    {
        "scenes": "Myscene",
        "source": "app/assistants/myscene-assistant.js"
    },
]

What this does is expose the contents of myDataModel.js globally to your app (so be careful with your globally scoped variable names!).

Typical round trips

Based on TapNote’s design (in which I tried to follow the above guidelines), this is a typical function layout for the controller:

  • Request function: this is typically triggered by an event in the view, and all it does is request something from the model (passing along any relevant info from the event, along with the callback function reference)
  • Callback function: this accepts data from the model, and does whatever needs to be done with it in the view.

A typical controller would thus look like this:

var MysceneAssistant = Class.create({
    /* Standard function for Prototype classes */
    initialize: function() {
        this.model = new MyDataModel();
        // Always save static bound references to member functions
        this.bound = {
            populateData = this.populateData.bind(this)
        };
    },
    
    /* ... Setting up events etc. happens here ... */
    
    /* This function is triggered by an event */
    refreshData: function(event) {
        // Any necessary logic prior to requesting data
        this.model.refreshData(this.bound.populateData);
    },
    
    populateData: function(dataObject) {
        // Handle populating the view with the data object here
    }
});

My model ended up being very similar, since it too had an asynchronous call (although if you were accessing data in a depot or cookie you might not need two functions):

  • Request function: receives requests from the controller, builds the necessary SQL (or whatever) and executes it, binding the callback into the success function of the datastore
  • Return function: processes the successful results from the query, and sends the results of processing to the callback

Using the previous example code for the controller, here’s how our model class would look:

var MyDataModel = Class.create({
    /* ... Set up the model here ... */
    
    refreshData: function(callback) {
        // Set up the SQL, etc. here
        // Query the database here binding in our unique callback
        this.db.query(query, {
            onSuccess: this.returnData.bind(this, callback)
        });
    },
    
    /* Because of the on-the-fly bind, the callback is the first arg */
    returnData: function(callback, results) {
        // Transform results into Javascript object; simple example:
        var resultObject = results[0];
        // Send the object to the controller
        callback(resultObject);
    }
});

Unlike the controller, in the model we have to do the binding on the fly because otherwise we can’t pass the callback through. If you can guarantee that there will only ever be one controller requesting data at any given time, you could instead use a this.bound object like the controller and save the callback to a class variable (for instance, this.callback).

Brief side note: you may notice the unexplained this.db.query() call above. When I was writing TapNote, one of the first things I did was write a generic Database class to abstract away from the heinous syntax of the HTML 5 database connection. This is a generically useful class that I’ve released for free.

Implementing in your own app

The above examples certainly are not the only way to do things (I actually deviated from that design a bit for some data responses when TapNote became a multi-stage app partway through development), and you will likely find yourself changing things up based on the needs of your own app. However, if you start with this design as a basis and keep in mind the roles and responsibilities of model and controller, then you will hopefully create an app whose code is easy to debug and expand on down the road.

The pricing of TapNote

Once I’d finished up the basics for TapNote 1.0, I faced the difficult task of choosing a price for it. After much deliberation, I settled on an asking price of $4.00. This price appealed to me because it was in keeping with the pricing for the better-class note-taking apps available in the app catalog, but wasn’t a .99 price point (which I hate; I think they’re dishonest, and even if they perform better—something I doubt—I’d rather provide an upfront price to people rather than trying to trick them into rounding down in their head).

Then Palm approved TapNote, I excitedly posted about it here and on Twitter, and absolutely no one bought it. A week later, my Palm stats have a number of purchases I can count on one hand, and no one has cared enough to leave a star rating, much less a review of the program.

This is, to say the least, discouraging.

Since then I’ve been vacillating between leaving the price as-is and sharply cutting it. A fellow WebOS developer on Twitter recommend cutting the base price in half and reducing it further as a promotion to drive initial sales and hopefully get on the Hot Apps list. This was tempting, since the whole reason I released version 1.0 without synch was that I wanted to get it out in the window for Hot Apps.

However, I truly believe that TapNote is worth $4.00 (or more, to be honest; $4.00 won’t buy you a decent lunch, and what I’m planning to do with TapNote 1.x is way better than a decent lunch), but what I believe and what the market is willing to pay are two different things, so if I want to sell it I’m going to need to conform to the market’s expectations.

After giving this lots of thought, waiting to see specific numbers in Palm’s download reports, and sleeping on the problem, I’ve made up my mind: I’m leaving the price alone. People can either cough up four bucks if they, like myself, aren’t happy with the existing options for note-taking, or they can settle for one of the existing solutions. I’m unlikely to sell many copies up front, and unless a high profile blogger or review site notices TapNote and gives me some favorable press there’s no way I’ll even make it into the lower tier of Hot Apps, but I’m alright with that.

First off, I don’t need the money. I created TapNote because I badly needed it, and although I’d like a little recompense for all the time and effort I’ve spent, I’ve already got a full time job that’s paying the mortgage. It makes me a little sad that other people don’t appreciate TapNote, but it won’t impact me negatively if TapNote remains in obscurity for a while (and the nonexistent support burden is definitely nice).

Secondly, the whole race to the bottom that continues to occur in app stores leaves a bad taste in my mouth. Developers complain about how they sink months into an app and then people won’t even give them the cost of a cup of coffee for it, yet they still slash prices down to nothing in an effort to sell. In the Apple app store, this is about the only option, of course, because the competition is so heavy it’s virtually impossible to get noticed. For the Palm app catalog, though, there’s relatively little competition. Just keeping an app on the “Recently Updated” pages with regular updates is enough to get a reasonable amount of exposure (based on things I’ve read in the developer forums).

So cutting the price when I don’t really need the sales feels to me like devaluing the app for no good purpose. Increasing prices for high quality apps has to start somewhere, and to be honest $4.00 is hardly a high premium. Based on my competition, a premium price would actually be up in the $7-10 range.

Additionally, I am highly skeptical that vastly reduced prices is actually profitable. Certainly it’s useful for getting an app into the public eye, but when I look at the apps in the $10,000 bracket of Hot Apps, very few of them cost less than $5 (and of those less than $5, most are at the $3-4 mark). Palm has been crowing about TweetMe’s meteoric rise up the charts, but I notice that it remains in the $1,000 bracket, while it’s higher-priced competitors are looking at a handy $10,000 bonus and a $4 notes app that was featured in the app catalog’s Feature Apps area has quietly jumped into the $10,000 bracket, as well.

All of which says to me that although cutting prices would probably get TapNote noticed, I would have to time things very carefully in order to not ultimately lose profits. Because Palm’s download reporting for paid apps is almost a week delayed (!!!) and any price change requires at least 2-3 days while they review it, it is virtually impossible for me to tweak the price lower and then raise it back up when its usefulness has run its course. If I’m going to lower it, I need to be content with it being lowered for a week at minimum and more like two weeks before I can accurately judge the effectiveness of the change.

None of which is worth it to me. I would rather continue as I have with a solid product and great updates and then see if some marketing efforts once I’ve integrated synchronization don’t give it a boost in popularity. That way, I lose nothing, ultimately will likely make more money than if I halved the price and got a $1,000 Hot Apps bonus for it, and I don’t devalue my app in a market that hasn’t yet figured out that a lowest-common-denominator price doesn’t often make for a good user experience.

WebOS first impressions and the making of TapNote

About two months ago, I switched to a Palm Pre Plus to replace my iPhone. As soon as I got home I of course started playing with my new toy, and it did not take me long at all to realize that although Palm has included an excellent suite of default software and there are some wonderful apps in the app store, I was desperately going to miss WriteRoom on the iPhone. There were several note-taking apps already out, but none of them offered the features I needed in an attractive package. Most, in point of fact, tended toward feature-bloat by my standards.

And so TapNote was born. I created TapNote because I badly needed it, and I released it as a paid app because I figured other people would be interested, too.

Getting into mobile app development using WebOS was an interesting journey, so I wanted to share some of the things that I discovered along the way, as well as discuss the specific design decisions that influenced TapNote’s development.

WebOS: a quick intro

It’s pretty obvious that developing for WebOS means using web technologies, but what exactly does that mean?

Right now, there are two basic types of WebOS apps and a third on the horizon:

  1. SDK apps are coded entirely in HTML, CSS, and Javascript and leverage Palm’s Mojo framework to interact with the system hardware.
  2. PDK apps are coded in C or C++ and interact directly with frameworks like SDL to display things on the screen and interact with the user. The 3D games that you’ll find in the app catalog are all PDK apps.

The third type of application is one that mixes the web tech SDK with compiled C code in the PDK to leverage the strengths of both. We haven’t seen any such apps yet, because Palm hasn’t provided an API for communicating back and forth between Javascript and C.

The WebOS SDK: not all sweetness and light

Developing for WebOS has been an intriguing mixture of simplicity and frustration. I am a front-end web developer by trade, so WebOS sounded perfect to me: no new languages to learn, no need to muck around with compiled code, and the ability to use my current development environment. Although Palm is pushing Eclipse for development, I was able to whip up an Espresso Sugar for WebOS development my first weekend and hit the ground running the next week.

However, WebOS is not the panacea that it sounds. Web developers get pretty hot under the collar when they hear you can make true applications using HTML and CSS, but here’s the truth: you can’t. Coding for WebOS is about Javascript. Yes, you can do a certain amount using CSS animations, but for the most part it’s Javascript, Javascript, Javascript. Javascript to set up the HTML and register it to be transformed into widgets, Javascript to handle interactions with users, Javascript to set the classes that trigger your CSS animations. If you want to develop for WebOS, you need to know Javascript.

It isn’t like this is unexpected, of course. HTML+CSS isn’t optimized for handling touch-based interactions, and there is no concept of URLs for typical apps which means the only way to get new content is via asynchronous Javascript. So although the reliance on Javascript is obvious in retrospect, I mention it because most of the web developers I know have a hazy grasp of Javascript or know only jQuery and I don’t wish this to come as a rude shock. It’s also worth mentioning because the Palm documentation is terrible if you’re a Javascript newcomer.

Thankfully, I am not, but I pity newcomers to the language. Palm’s documentation is all vanilla Javascript, and filled with references to object prototypes and so forth. Then you boot up their example apps and discover that rather than eat their own dog food, they’re using the Prototype framework’s Class object to create a nice classical-inheritance object flow. Had I not been well-versed in the concept of using classical inheritance alongside Javascript’s prototypal inheritance from my past work with Mootools, getting up and running would have been a major headache.

Additionally, although Palm claims to support the latest web technologies, they do not. There are two reasons for this:

First, they enforce an awful, non-semantic div soup markup style. If you want to use a Palm widget to speed things up (which you mostly will, particularly the list widget), you have to declare it using a div and it is then automatically filled with a plethora of other divs. To make matters worse, the Palm example projects rarely use any elements other than divs (even when the element is clearly a header, paragraph, etc.) and there are no reset styles in the CSS that’s lumped in with the Mojo framework so if you end up trying to code something vaguely semantic you’ll have to restyle every element. Clearly Palm’s markup was developed by people who have never worked as front-end developers, and it’s a crying shame because it makes development on WebOS for people who care about writing elegant markup quite frustrating. And yes, good markup matters. Aside from making accessibility on the platform easier down the road, simple semantic markup is easier to style, read, and modify, which directly impacts development time.

Second, WebOS is driven by Mobile Webkit. The good side of this is that you have access to a whole new world of CSS and, to a far lesser extent, HTML (without needing to worry about cross-browser debugging! Huzzah!). The bad is that Mobile Webkit’s support of CSS 3 and so forth is inconsistent at best. For instance, when I was creating TapNote’s editing interface, I wanted to fade out the header pill when text scrolled under it rather than attaching the header to the top of the page. This was super easy: I just added a CSS transition to fade the opacity of the element down.

But the text remained at full opacity. After a bunch of experimentation, web searches, and so forth I discovered that Mobile Webkit (or possibly just the version employed by Palm) can’t apply opacity to an element’s text for some unknown reason. Not so helpful. (Thankfully in this instance, there was a workaround: Palm’s Webkit does support rgba() colors, so with some extra styles I was able to make the whole thing fade.)

Don’t get me wrong: I love WebOS and I think it is hands-down the best mobile OS on the market for developers. However, that doesn’t mean that you shouldn’t go into it with eyes open. WebOS is a great idea, and Palm has done some truly visionary work, but it is by no means perfect.

Diving in

I’ve thought a lot about design over the course of TapNote’s initial development. When I was browsing through the app store for a note-taking app, what struck me wasn’t that the available options were bad, per se. They just weren’t designed to the standards I’ve come to expect having used Mac OS X and iPhone software for so long.

This doesn’t mean that they weren’t visually appealing. For some of them, far from it. However, aesthetically pleasing design is not the same as having a well-designed interface.

A great example of this is Palm’s own Memos app. It’s a perfect example of software kitsch: visually appealing, but ultimately useless and reliant on a cheesy metaphor that has no applicability to the medium. A corkboard covered in Post-Its is a worthless conceit on a device where screen real estate is at such a premium, since aside from color you can’t quickly distinguish between notes without opening them. Add to that the fact that the metaphor has no basis in reality (Post-Its won’t stick to corkboard) and you’ve got an app that did not receive terribly deep attention to its design even though someone with great aesthetic sense obviously put some love into the graphics.

In short, the Memos app looks great and feels terrible, which means that it wasn’t well designed. Truly good design requires thinking deeply about the visual appearance and how it interacts with the app’s functionality (among other things, like whether a given bit of functionality is even necessary). Too many of the note-taking apps that I tried seemed like they were focused on implementing a targeted feature list in a visually appealing way, without thinking enough how those features and interface really impact the user experience.

I did not want to rehash these problems with TapNote, so when I started designing it I decided there were only three things I couldn’t live without:

  • Plain text editing
  • A document-based layout, a la WriteRoom
  • Wireless synchronization with my Mac

(Only two of those three bullets made it into version 1.0; synchronization sadly didn’t make the cut for the initial release because I had a soft deadline of releasing the first version during the Hot Apps contest to ensure that this didn’t become one of those software products that never gets released at all.)

I drew some sketches to make sure that the ideas I was picturing were worth pursuing, and then since most of the app relies on Palm’s provided styling anyway, I started straight into development.

With a framework like WebOS, I think this was the right move. Were TapNote more visually complicated, I would have needed to create some detailed mockups, but in some ways usability matters even more than visuals for a mobile app, and you won’t know how usable your app is until it’s in your hand.

Simplicity versus obviousness

For TapNote, I decided the single most important thing to me was interface simplicity rather than making everything as obvious as possible. As a result, I avoided buttons for a lot of the functionality in favor of items in the app menu and contextual menus (which can be accessed by touching and holding an item).

In many ways, this is in keeping with WebOS’s core design, and is a major difference between WebOS and iPhone OS. On the iPhone, simplicity often comes second place to obviousness. A good example of this is the ubiquitous back button in iPhone apps. The back button takes makes for a more complex interface, but it is also dead obvious how to return to the previous screen. WebOS, on the other hand, provides a universal back gesture that works in every app, obviating the need for the visual clutter of a back button. This increases the visual simplicity of apps, but increases the initial conceptual complexity because users have to learn the back gesture.

Both approaches have their strengths and weaknesses, but deciding which approach to take is a core design decision for any mobile app, particularly on WebOS (you don’t have as much choice on the iPhone, of course, thanks to the lack of support for back gestures or standardized app menus).

An example of how I followed this design path for TapNote is the “email document” function. I added this to the app when it became obvious that synching wasn’t going to make it for version 1.0, and the most obvious way to do it would have been to put a button with an icon at the bottom of the editing screen. However, this would add visual clutter to the app for an action that most users are going to utilize rarely, so I instead placed an “Email Document” item in the app menu for editing documents. Because it is hidden in the app menu, it’s unlikely that users will discover it without looking for it specifically (the downside) but it also streamlines the main purpose of the app, which is reading and writing text.

It’s the details

It wasn’t until I created the website for TapNote that I realized it’s not a visually impressive app. Yes, it looks good and it does exactly what I designed it to do (which is draw your focus to the text in a visually pleasing way), but it’s not flashy in quite the same way as an app like TweetMe. I was originally intending to do the classic “large phone with screenshot” approach for the webpage, but it didn’t work at all because any TapNote screenshot I took was just a bunch of text that distracted from the web page (and not quite enough text that I could fit the marketing verbiage I wanted in there).

Such a realization was a slight shock to me, because I’d been using TapNote at that point for about a month and it had always felt special to me. When I thought about it, though, it wasn’t special because it was outstandingly pretty (my designs rarely are; attractive simplicity is my forte), but because I’d focused my attention on the little details that matter in day to day use.

This is something that is overlooked far too often in mobile development. For instance, when I downloaded other note-taking apps, a common thing I would do was tap the new note button, tap the title, type a title, and then tap right at the bottom of the screen (right above the keyboard, where my hands already were) to place the edit cursor in the main text field.

The only problem with this was that none of the apps I did this in actually placed the cursor in the main editing text area. After my tap, I had to start tapping up near the top of the page, hoping that I’d hit the nebulous text input so I could start typing.

So in TapNote, although it took a bit of work (and got inadvertently broken several times during the course of development), I made sure that on short documents tapping below the editing area would place the cursor at the end of the editing area.

I’m a firm believer that this is the type of detail that deserves the most attention in mobile apps (and frankly thanks to my self-imposed deadline I didn’t focus on quite as many of these little details as I should have; I’ve been talking up TapNote like it’s the One True App, but as is always the case in a 1.0 product, my ideals are in a far better place than the actual product ended up).

Moving forward

Palm’s WebOS provides a unique opportunity for web developers to explore a new market and interaction framework for their development, and I have no regrets about investing effort into learning the Mojo framework to develop TapNote. I love creating websites, but designing something that I can carry about in my pocket and use every day has a special kind of appeal.

Although I’m happy with how TapNote 1.0 turned out, I’ve got a lot of work still to do. I’ve barely scratched the surface of my ultimate vision for the app, and for all my lofty ideals of great design I didn’t spend quite enough time on a few aspects of the app in my attempt to get it out the door.

My hope is that others will find my early experiences and opinions on design useful in their own development processes, whether they agree with my approach or move in an entirely different direction. Developing TapNote has been a great and ongoing learning experience for me, and I hope other people will take the same leap into WebOS development. This is an area where high attention to detail is not yet the norm and (unlike the Apple app store) there’s lots of room for innovation and improvement on existing solutions because the app catalog is nowhere near as saturated.

Announcing TapNote

I’m very pleased to announce that TapNote, my dead-simple note-taking app for Palm WebOS phones, is now available in the Palm App Catalog for $4.00. I’ve been working on TapNote ever since I picked up a Palm Pre and discovered that none of the notes apps made me happy.

Version 1.0 has all the basic functionality that I needed to take notes comfortably on my phone, but I’ve got some fun plans for the 1.x line (easy-as-breathing synchronization being my top priority). If you have any feature requests or annoyances with the app, let me know!