Skip to content

Hey! This is my old blog, and is only preserved here for historical purposes. I\'m now blogging at nate.io instead!

Getting to Why

Earlier this year, a TED talk by Simon Sinek made its rounds on the internet. In it, Simon compares the marketing strategy of companies like Apple to the rest of the industry. Niki and I saw the video if the talk right after we’d closed the acquisition deal selling AgileZen to Rally, and it codified a lot of the ideas that we’d had while launching the business.

Simon argues that most companies approach marketing in an entirely backwards fashion – focusing on describing what they are in business to sell. Companies like Apple instead focus on understanding and explaining why they exist. In so doing, Simon argues, Apple speaks to the more primal nature of their customers, appealing directly to their emotions rather than convincing them with logical arguments.

The same effect can be seen in the rise of Audi, whose car line was once considered an afterthought to BMW and Mercedes-Benz, but is now one of the fastest growing luxury car brands worldwide. Their marketing certainly talks about the quality and performance of their cars, but they mostly focus on their company’s way of thinking versus the other German luxury brands.

When I first saw Simon’s talk, I immediately recognized that the same motivation can be found not just in marketing techniques, but also in product development and the creation of a startup.

We didn’t do it deliberately, but I think this is the reason we’ve seen a good deal of success with Zen. When we first started talking about the idea that would eventually become Zen, we were primarily motivated by the idea that all of our competitors’ products were too complex to serve a the massive small-to-midsize business market. We decided at a very early stage that we were in business to convince others that less software is better. It was this idea that led us to creating a simple, approachable tool for managing work – the what resulted from the why, rather than the other way around.

Since features inevitably lead to complexity, we actually focused on implementing as few features as possible. In a feature-to-feature comparison, we’d lose against many of our competitors, but we don’t want to sell a product. We want to sell an idea – that most software is much too complex, and the majority of features simply add noise to the signal. Our customers may not realize it, but this is why they buy Zen. Being less of a product has given us double-digit revenue growth every month since we launched without a sales staff and without much of a marketing budget.

Simplicity, of course, is not always the how that successful companies strive for. Apple’s how is more about its aesthetic and challenging the status quo of computers as chunky black boxes that are hard to use and understand. The iPad is an unbelievably complex device, with a custom processor and operating system – but Apple owns 90% of the tablet market share because it’s a beautiful product that challenges the status quo. Audi’s cars are likewise complex, powerful performance machines.

Apple has been so successful in selling this idea that ownership of an Apple product is often a source of pride and an indication of success. Of course, this is also due to the price point at which they sell their products, but if they weren’t able to offer a compelling differentiator against their competitors, they wouldn’t be able to sell their products for the prices they do.

We’ve seen similar behavior in Zen’s uses – not necessarily the pride of ownership, but definitely the desire to tell others about the product. We simply wouldn’t still be in business without our customers selling our product by word of mouth.

The same effect can be seen in other fields as well, with one of the best examples being politics. Many intellectuals lament that the majority of modern political discourse doesn’t come anywhere near discussing the actual issues that affect us, with politicians instead just making pleas at the basic emotional nature of their constituency. If you live in America, this idea is almost certainly burned into your short term memory from the recent barrage of campaign commercials, most of which just slung mud and invoked bogeymen, without offering any actual solutions.

Is it that politicians don’t have ideas? Of course not – they’ve simply realized that by appealing to emotions, they can optimize the incredibly small amount of time they have to can grab the attention of the most people possible.

At the risk of proselytizing, I’d also argue that this is why the GOP was so wildly successful in the most recent elections, as well as in 2000 and 2004. As a group, they understand and agree upon how to deliver a unified message concerning why they exist, at least much more so than do the Democrats. This is the reason Republicans can convince so many people to vote against their own economic interests. It’s also why people buy and love Apple products, even if they understand and disagree with the closed nature of OS X and the iOS ecosystem.

Understanding the base reasons for actions can be used for good and evil. Most everything worth doing requires convincing others that it’s worthwhile – whether it’s launching a business, selling a product, running for office, or applying for a job. By taking a moment to develop a cohesive message of why you’re doing what you’re doing, you can turn humankind’s emotional nature into a powerful megaphone that will amplify your message.

Looking Back

For readers who don’t know, our startup was acquired by Rally Software at the end of March. As things started to calm down a bit, I remembered that I had a blog, and decided I should look back on my time as a co-founder of a startup.

Launching AgileZen was hard. Well, the act of launching was easy — all you need to do is deploy your site and tell some people — it was the lead up to it was difficult. Actually, the hardest part was to convince ourselves that we could actually make this work, and to stay focused enough while still holding a full time job to build enough software to validate the idea. I was fortunate enough to have a great co-founder/wife and a group of friends to be able to keep myself on target.

When I left my full time job in mid-May, we didn’t have much. The product wasn’t really more than a prototype, and the marketing site was non-existent. We had a good grasp of our business model, but we had no branding and weren’t really sure how we were going to sell the product. When I walked away from my job with the idea we’d launch on July 7th, we had six weeks to build something real and convince people to pay money for it.

If I had to guess, I’d say I worked about 500 hours in those six weeks. Niki put in a huge amount of time on design, testing, and copywriting, but she still had obligations at school and most of the hours were spent grinding out code anyway. I have to admit, by the end I was only partially lucid. A few nights I’d wake up in the middle of the night with ideas and, not being able to get back to sleep, I’d get up and start working. Although, that led to some interesting creative moments: the performance screen in AgileZen was one of the last things I built, and at launch, I felt it was one of the better-designed parts of the app.

I’m not complaining, though. Far from it. Building AgileZen in those six weeks was one of the hardest things I’ve ever done, but I absolutely loved it. It made me remember what it was like to build something because you loved it, not because nameless customer X needed it for generic business process Y, and not because it was the next story or defect in the backlog.

It also completely changed the way that I look at software. I’ve tried to express this to others since, but I think you just have to experience it firsthand in order to really understand. It’s a unique experience to build a product of your own, from scratch, with no paycheck or deferred responsibility or venture capital to save you — you either create real value for your customers, or you fail. And I don’t like to fail.

To be successful at bootstrapping, you have to cut every feature except those you think are absolutely necessary. Then you cut some that you thought that you absolutely had to have. You compromise your design because you need to get the product to market. You ignore automated testing and documentation because your code is too unstable to be held back by rigorous processes.

I built AgileZen unlike any other piece of software I’d built. I cut corners that I would never have thought of cutting if I was working a day job. And you know what? It didn’t matter. We launched on schedule, we crushed our user and revenue goals, and our customers raved about the usability of the product. No one gave a shit about what our test coverage numbers were. Our software made their job or life easier, and that’s why they bought it.

Now, I’m not saying every product should be built this way, but it certainly shifted my perspective on what’s vital and what’s not when building software. AgileZen was built with an architecture that I’m still very happy with, but on top of the strong foundation there was a lot of kludge. That being said, if there was code that was hack-and-slash, I did my best to isolate it. The trick is to know which parts of the app are “load-bearing,” so to speak, and which parts can be safely patched together.

After we launched, I spent the month of October basically rewriting every line of JavaScript in the app to create a more maintainable structure. Was it wasteful to throw so much code away? Maybe, but we were up and running, and we were making money. Before we could afford to spend a lot of time to make the software maintainable, we first had to prove that we would actually have to maintain it — we had to make sure that we actually had a market. Your app can have the best architecture and be 100% defect-free, but if no one cares what it does, it’s wasted effort.

The key thing I learned was that when your time is so restricted, you can’t solve problems that you think you might have some day — you have to spend all your time on the problems that you have right now. You have to have an overall vision to guide you to your goal, but you need to keep a laser focus on the next step towards it.

The last year has been quite an experience. Startup life is stressful and painful and wonderful. I learned more about software and business and myself than I ever expected to. We had a successful exit, which is the brass ring lots of startups look for, so it’s easy for me to look back without regret. Still, I think even if we had flamed out it would still have been worth every bit of effort for what I learned in the process.

We love working for Rally, but at some point in the future, we’ll be back.

Ninject Forever

I’m happy to announce that after quite a while in beta, Ninject 2 is finally official! It was actually one year ago today that I announced the beta version of Ninject 2. I had originally planned to release no later than March of last year, but in the meantime I had this crazy idea to launch a startup.

As you might imagine, I quickly found that running a business has a tendency to sap your free time.

Fortunately, after Ninject laid dormant for a bit and I was conspicuously absent on the user group, Ian Davis contacted me to offer his help. Ian was a user of Ninject since way back (when it was still called Titan), had committed patches, written extensions, and had more or less taken over answering questions on the group in my absence.

So, please join me in a officially welcoming Ian Davis as co-maintainer of Ninject! Without his help, we probably wouldn’t have made it to an official 2.0 release, at least for another year or two. 🙂

Note: Ninject 2 is a ground-up rewrite of Ninject 1, and as such, there are some breaking changes. We’re still working on getting the documentation migrated over (along with upgrade guides), but you can see a quick overview of the differences on the Ninject 2 wiki. I’d strongly recommend upgrading, because no future work will be done on the Ninject 1 line, other than critical bug fixes.

The official source repositories for both Ninject 1.5 (the final version of the Ninject 1 line) and Ninject 2.0 are on Github:

The subversion repository on Google Code has been discontinued for awhile, and will be removed soon. You can also grab binaries from the shiny, newly-redesigned website. (Now with even more ninja references!)

Thanks to everyone that uses Ninject, and thanks for your patience as we scrounged the time to get this release out the door! As always, if you have any questions or feedback, please feel free to post them in the user group.

Note: the title of the post comes from James Avery, who had taken to calling Ninject 2 “Ninject Forever,” in reference to Duke Nukem Forever. At least we finally released something! 🙂

Justin Etheredge’s LINQ Challenge

Justin Etheredge just wrapped up a series of videos on LINQ for TekPub, and when announcing it, he offered a challenge with the following rules:

  1. You have to blog about a single LINQ query which starts with Enumerable.Range(1,n) and produces a list of prime numbers from the range.
  2. You can’t cheat. This is determined by me, and includes hardcoding values in the results. You’ll know if you cheated.
  3. Uses no custom LINQ methods.
  4. Will return all of the prime numbers of the sequence. It doesn’t have to be super optimal, but it has to be correct.
  5. Be one of the first 5 people to blog a correct answer and then tweet this "I just solved the @tekpub LINQ challenge: <link to post>" will get any single TekPub screencast. The time of your solution will be based on your tweet! So be prompt!
  6. You must link to both TekPub’s website and this post in your blog post.

I can’t resist a good brainteaser, so here’s my answer. I’m sure it’s not the most efficient way of solving the problem, but it works:

var max = ...;
var primes =
  Enumerable.Range(1, max)
    .Where(x =>
      x != 1 &&
      !Enumerable.Range(2, (int)Math.Sqrt(x)).Any(y => x != y && x % y == 0));

But, I’ve already got a subscription to TekPub, so I don’t need the prize! Instead, I’m going to give it away to the first person who comments on this post. If you haven’t seen TekPub yet, you should check it out! It’s a great resource for programmers of all levels of skill.

Guarantees, SLAs, and Hollow Promises

Since we launched Zen, we’ve received an interesting question a few times from prospective customers: if a company commits to using Zen in their organization, what happens if we go out of business? As a startup, what sort of guarantee can we offer to our users that we’ll be around years from now?

It’s a reasonable question, but one that doesn’t really have an answer. While I’m flattered that someone would accept my word, any promises that I would make would be hollow. That isn’t to say we’re going out of business (far from it, I’m happy to say!) – but if the recent economic turmoil has taught us anything, it’s that no business is immune to the effects of the market.

Instead of offering hollow promises, we’ve tried hard to set up our business model to allow the only two things that really matter to a customer of a software-as-a-service company like ours:

  1. The ability to cancel anytime, for any reason, without penalty.
  2. The ability to extract any user-generated content that you added to the system.

With these two simple rights, customers have a great deal of freedom. By removing the cost of canceling (or at least reducing it as far as we can), we’ve removed a great deal of the power we would otherwise have over our customers. A vendor-consumer engagement is pretty similar to other relationships – if one side expects a high level of commitment, the other side expects to receive the same level of commitment as well.

Another question we’ve been asked is whether we offer an SLA (service level agreement). If you’re not familiar with SLAs, many companies offer them on subscription-based services to guarantee a certain level of service. They’re usually measured in nines – for example, three nines would mean the service would be guaranteed to be available 99.9% of the time. If the SLA is violated, it typically means the customer is refunded some pro-rated percentage of their subscription fee, depending on how long the service was unavailable. The customer is also sometimes allowed to terminate a contract without penalty if the SLA is repeatedly broken.

Some people have been shocked to find we don’t offer an SLA, but just because we don’t agree to guarantee a certain level of service doesn’t mean that we don’t care if Zen goes down! Simply put, we don’t offer an SLA because it wouldn’t offer anyone anything real, and we don’t like lying to our customers.

Here’s a quick example. Let’s say we offered a three-nine SLA, so Zen has to stay up for 99.9% of the time or we owe our customers refunds. For a 30 day month, this means Zen can’t be down more than about 43 minutes to remain within the SLA. Let’s also say that if we violate the SLA, we refund the pro-rated amount for the contractually-guaranteed time that we were down.

So, Jane Doe signs up for a Pro account for $29/month. In that month, a nightmare scenario occurs, and Zen is down for eight hours. That’s not a usual outage, where we’re down for upgrades or patching the server, this is a full-on, sky-is-falling, dogs and cats living together, mass hysteria sort of situation.

With a pro-rata refund SLA, here’s what Jane can recoup:

100% uptime: 43,200 minutes
99.9% uptime (guaranteed by SLA): 43,157 minutes
Down for 8 hours (480 minutes), actual uptime would be: 42,400 minutes
Missed SLA by: 43,157 – 42,400 = 757 minutes
We owe Jane: ( $29.00 / 43,200 ) x 757 = $0.51

Again, this is a worst-case scenario, and if Zen was unavailable for that long, refunding fifty cents to our customers is just adding insult to injury. That’s why we don’t offer an SLA. They’re for companies that charge thousands of dollars for their service, or lock their customers in to long contracts.

Not only that, but that SLAs actually create hidden costs for customers. In order to support a strong SLA, a company is forced to do things like set up hot backup servers, clustering, with redundancy in power and network – not to mention write some sort of instrumentation to determine how long the system was actually down (with redundancy, in case that system goes down).

We pay our hosting facility good money to take care of a lot of those things for us, but high-availability is expensive, and the cost ends up getting passed on to the customer. When a company offers you an SLA, you’re paying extra each month to ensure that if something bad happens, you’ll get some of your money back.

The only guarantee I think it’s fair to offer our customers is that we’ll do the absolute best we can, and that if they’re not happy for any reason, they can always leave with their data intact.

A Few Lessons Learned

Running a business is nothing if not a learning experience. Every day presents a situation that you haven’t encountered before, and you have to be ready to shift your perspective and learn quickly in order to adapt. Here are a few tidbits of information that I’ve learned (sometimes the hard way) so far as we’ve been running Zen.

Save more information than you think you’ll need.

Disk space is cheap, and it’s much more difficult to migrate (or generate) missing data after-the-fact than it is to collect it when something happens. At a minimum, you should have a transaction table that captures everything that happens in your system. That way, you can always use this table as a last resort to create new data if you need to in the future. Be sure to listen when your conscience says YAGNI, but never trade off knowledge for extra disk space.

Soft-delete everything.

Instead of actually deleting information from your database, just flag it with a “tombstone” and leave the record there. Not only does that allow you to recover data if a user accidentally deletes it, but maintaining the relationships between entities makes managing the data much simpler. Sure, you end up with stale data in your database, but you can always prune it after a certain period of time to clean things up – and since this pruning operation takes place out-of-band, if it doesn’t work perfectly your users aren’t bothered by it.

Don’t underestimate the cost of meta-work.

Not everything that is necessary is customer-facing, or even directly related to the product. I refer to work that’s important, but not quite value-adding, as meta-work. For example, one of the most complex parts of the Zen codebase is actually the billing system – customers don’t interact with it directly, but they would definitely be upset if Zen randomly billed their credit card! The most important parts of your product are usually the parts that no one knows exist – that is, until they don’t work the way they should. 🙂

Don’t skimp on administrative software.

Information is power, so make sure your system tells you when things happen. Write reporting and management screens. Make your software send you emails when things happen. Balance this against the previous point, but just because something isn’t customer-facing doesn’t make it wasteful – if an administrative screen or report helps you to serve your customers better, it adds real value. Don’t do too much up front; instead, wait until you recognize opportunities to improve your operations, and pick the low-hanging fruit.

Just a few random thoughts. 🙂

Open Source is not a Zero-Sum Game

I had originally left off the name of the person I was talking about because this post isn’t intended to make him sound like a bad guy. However, he felt I wasn’t being conversational, so the person that triggered this post is Sebastien Lambla, author of OpenRasta. Read his response here.

I caught some flak on Twitter today for releasing Siesta as open source. It was the same song that I heard when I wrote Ninject, which was: why are you reinventing the wheel? Normally I shake that sort of thing off, but once I found out that the person complaining was the author of a “competing” REST framework, it ruffled my feathers a little bit.

Siesta originated as part of Zen. Implementing REST is not a difficult problem, and I’ve done it before. (Most of the difficulty is in mapping HTTP requests to method calls, which ASP.NET MVC handles for you.) Since I knew exactly how I wanted it to work, and had a reasonable idea of how to implement it myself, I just sat down and wrote it.

Could I have used an existing open-source framework? Sure, but I’d never heard of any other than WCF REST, which I already knew didn’t match my mindset. I searched for a little while on Google to find other libraries, but didn’t find anything. I’d also argue that REST is so low-level that it would be very difficult to come up with a clean drop-in solution – that’s why I suggested that Siesta is more an example of how to write a REST system than it is a reusable framework.

I believe very strongly in not falling prey to the Not Invented Here syndrome. Like I said in my previous post, Zen uses a myriad of open source libraries:

I’m all about standing on the shoulders of giants. 🙂 However, rolling your own is not always waste. The bits that became Siesta took me about a total of 4-5 hours to implement end-to-end. That’s much less time than it would have taken me to find a framework, understand how to use it, evaluate whether it would work for what I needed, and integrate it into Zen.

Like I said, I’ve written several RESTful systems before, using MonoRail and raw IHttpHandlers – but none of them belonged to me, so I couldn’t open source them. Because I already understood the problem well, it was actually less expensive for me to write my own implementation.

As the owner of a startup, I have to justify the value of everything that I do to ensure that I’ll get a decent return on investment. In order for me to consider using an external framework, I have to be relatively certain that I’ll save time by using it in the long term. This leads me to my point:

It’s not my fault if I don’t know about your product. It’s your fault.

If you don’t market your product well enough for me to know about it, and I can’t even find it when I’m looking for it, it’s never going to get on my radar. It doesn’t matter if your product is free and open source or costs thousands – if I even don’t know it exists, how in the world am I supposed to make the difficult decision to use it?

That’s my first problem with the complaints about Siesta. My second problem is this: I spent my time and money to develop the part of Zen that became Siesta, and because other people have previously asked me for help on the topic, I’m happy to share it with anyone that’s interested, free of charge.

It’s my code, and I’ll do what I damn well please with it.

I haven’t always thought this way, but these days I don’t care much about mindshare or competition in the open source space. I spend enough time competing on my commercial endeavors, which have the distinction of putting food on my table. Open source is something I do because I want to help.

Siesta’s not perfect and it’s not the only solution, but it represents the way I think a REST system should be implemented. If you don’t like it, don’t use it. Even better, tell me what you don’t like about it so I can learn from your perspective just as you can learn from mine.

The goal of open source is not to develop a single solution that can be used in all situations. In fact, it’s the opposite: open source thrives on competition. If you feel threatened because someone else releases something that you perceive as competition, maybe you should rethink why you’re working on open source in the first place.

Siesta: Painless REST via ASP.NET MVC

Zen uses quite a few open source libraries, and I feel a sense of responsibility to contribute back where I can. To that end, I’m releasing the basic infrastructure that powers the Zen API under the name Siesta.

Siesta is a simple and flexible REST system driven by ASP.NET MVC. While you can take the Siesta bits and use them directly in your app, it’s intended more as an example of how to implement your own system.

The basic idea behind Siesta is to communicate only using models within your application, and allow the infrastructure to handle the serialization and de-serialization, similar to how a view engine manipulates ViewModels or ViewData. Models are just POCOs, and serialization is controlled the [DataContract] and [DataMember] attributes in System.Runtime.Serialization (so yes, this requires .NET 3.5).

Siesta also uses the (sweet-with-extra-awesomesauce) JSON.NET library from James Newton-King. There’s a DataContractJsonSerializer in the BCL now, but as far as I could tell, it doesn’t support indentation. JSON.NET supports both, so it’s a great fit. I’ve also been using it forever, so I’m just used to it – if you deal with JSON formatting, it’s definitely worth a look.

The wire (serialization) format is based on MIME types, and Siesta comes with XML and JSON built-in. However, it’s also extensible by implementing a new IModelSerializer. Speaking of which, if someone wants to implement one for YAML, it would be greatly appreciated. 😉

As described in the Zen API documentation, the wire format is determined by the Content-Type and Accept headers. Content-Type is preferred for incoming data, and Accept is preferred for outgoing data. If a header is missing, the system will fail over to the other one.

Here’s an example of an entity that can be serialized via REST:

[DataContract(Name = "user", Namespace = "")]
public class User : IEntity
{
  [DataMember(Name = "id")]
  public int Id { get; set; }

  [DataMember(Name = "username")]
  public string UserName { get; set; }

  [DataMember(Name = "name")]
  public string Name { get; set; }

  [DataMember(Name = "email")]
  public string Email { get; set; }
}

And its matching controller:

public class UserController : SiestaControllerBase
{
  public IRepository<User> UserRepository { get; private set; }

  public UserController(IRepository<User> userRepository)
  {
    UserRepository = userRepository;
  }

  public ModelResult<User> Get(GetRequest request)
  {
    User user = UserRepository.Get(request.Id);

    if (user == null)
      throw NotFound();

    return Model(user, request.Formatting);
  }

  //...
}

Don’t worry, SiestaControllerBase is just a simple base controller which provides the Model() method shortcut. This (and the IEntity interface you might have noticed on User) are entirely optional, and are actually part of the Siesta.Example assembly rather than the main Siesta assembly. As long as the types you want to communicate with are serializable, they’ll work with Siesta.

In contrast to the Siesta example, in Zen, we actually have separate models (which act as DTOs, and are serialized to/from a wire format) and entities (which are persisted to the database). The example doesn’t show this because it requires a whole separate mapping step, which can get tricky. I would highly recommend that if you use this in a real-world app, you create a separate type hierarchy and map between them.

Anyhow, you can grab the Siesta bits on GitHub, including the full version of this (simple) example. If you have feedback, by all means let me know! There’s actually quite a bit of stuff in Zen that I’d like to release as OSS – it’s just a matter of getting the time to split the code off the product and wrap it up.

Beginning ASP.NET MVC 1.0

Earlier this week, the UPS delivery guy surprised me with a copy of Beginning ASP.NET MVC 1.0 by Simone Chiaretta and Keyvan Nayyeri. I haven’t had a chance to read much more than just a brief skim of it so far, but I had an opportunity to review some of the content before it was published. What I’ve seen looks great, and I don’t just say that because it talks about Ninject. 😉 I plan to dig into it further when I can scrounge a few minutes.

Congratulations to Simone and Keyvan for finishing the book and getting it published! It looks like a great resource for aspiring ASP.NET MVC developers.

If you want to learn more, you can check out Simone and Keyvan’s posts.

The Media Blitz Continues

In addition to working hard to improve Zen, I’ve also been talking about it to anyone that will listen. 🙂 I’ve been fortunate enough to be featured on a few podcasts over the past few weeks to discuss lean, kanban, and Zen:

First, Scott Hanselman had me on Hanselminutes in mid-July. This conversation was a quick introduction about lean and kanban, with a few tidbits about Zen sprinkled in. I already mentioned this before, but the post was a 30-second-hurry-up-and-publish-and-then-get-back-to-grinding-out-code, so I figured I’d do it a bit more justice. 🙂

Then, the guys at Herding Code had me on to talk about the technology behind Zen, and the process of launching a company. This turned into a great conversation, although I wasn’t quite lucid by the end. (I’m not sure you can tell by listening, but I’d put in 16 hours that day and by the end of recording, it was 1:30AM EST!)

Last, but certainly not least, I was featured on .NET Rocks, where I talked with Carl and Richard about the idea behind Zen and my best understanding of lean and kanban. This was the first time I was on .NET Rocks, and I think it turned into a great conversation.

That’s all the podcasts that I’ve recorded so far, and without something new to talk about, I’m not sure I want to do too many more. I’m sure the audiences of the podcasts overlap, and by now I must be starting to annoy people. If so, sorry about that! 🙂

Anyhow, a huge thanks to the hosts of the podcasts, and everyone that listened. I’m obviously excited about this stuff, and I hope after listening to me ramble, others get excited about it too.