Category: Blocks

  • A Twin-Star Site Model

    I don’t love the name, but I think the creator economy is a real-enough thing. There are at least a couple million creators on the web, I read somewhere, who make a living at it.

    My impression is that they either go with something like Patreon or Substack as a way to platform themselves, or use Gumroad to sell things, or exist more or less entirely on YouTube, raking in the ad money. Maybe you can run your whole shop on Patreon (they’re introducing a community capability, founder Jack Conte even has a whole theory about how this makes sense and indeed, he does make some sense).

    Creators and cobblers

    It seems like most creators cobble both their online presence, the tools they use to manage that presence, and the back-end tools for accounting and stuff out of various pieces.

    I suspect a lot of time gets wasted in the cobbling and the learning involved with these tools. Fact of the matter is, for most creators, they typical tools are just way to feature rich and, as a result, complex.

    I’m not a creator in the sense that I’m talking about in this post, but I have done some of my own cobbling, enough to notice that, for instance, Quickbooks is just way, way, way more capability than I need, because all I need is to send out and track a few client invoices. And at nearly $40 a month for Quickbooks, I’m paying way too much for the privilege of letting them email my invoice forms.

    So I’m dropping Quickbooks in the new year and the general plan is to eat my own dog food. (I hate that expression, I think because I find life analogies that use food inherently coarse. But I can’t think of a better alternative–send help.) I’ll use PeakZebra to knock out a dead-simple invoicing system.

    PeakZebra(s)

    Whatever I pull together using PeakZebra, my plan is to evolve PeakZebra to support a “twin site” scenario where one site (PeakZebra.com) is the public facing site and another site (PeakZebra.something_else, presumably) will handle the back end things.

    This means that some elements will reside on the front-facing site, things like newsletter signup forms, to pick the simplest example. But when that signup form is submitted, it will be sent via an API call to the PeakZebra code on the backend server. The data from the form will be stored in the backend server’s SQL database, and when it comes time for me to do something with the data stored there, I’ll log in and use apps on the backend, while the front end site hums merrily along.

    Enhanced security

    With the right setup, this is a more secure approach to managing things like subscriber data, because you can put a lot of controls in place around who access that site than you can on a site that you want anyone and everyone to be able to at least see. And while WordPress is secure when properly configured, it’s safer still if the data isn’t even on the visible site.

    We’ll see how this goes–it’s not an immediate priority to have a “twinned” site arrangement, but I can still work on the sorts of simple tools I want, running them for now on PeakZebra.com but eventually migrating the backend stuff to a backend WordPress install.

    Is a twin site actually more secure? I think so, but I also think the crux of the question comes down to how secure you think the API calls that the front will make to the back will be. For my money, those can be locked down pretty darned tightly.

    You wind up with an arrangement that most attackers won’t have encountered before, with API calls being made from server to server. The attacker will not ordinarily have any way to see the API request data, nor will they be able to see the second server on the net unless they find themselves within a fairly narrow IP address range.

  • Creating a Block with Cursor AI

    I’ve been trying to figure out what the best approach to getting the most productivity out of AI-assisted coding in Cursor. Some things work jaw-droppingly well. Others create a rabbit hole of inexplicable coding failures that are more trouble than they are worth to debug and make work.

    Here’s a very simple example of something I was working on this morning: I wanted a WordPress block that would show an alert on a page with whatever message I put into it, and I wanted it to disappear on its own after it had been on screen for ten seconds.

    Keep it simple

    The takeaway, if you don’t care about the details, is this: you should stick to relatively discrete steps you’re asking it to achieve and you should check each bit carefully as you assimilate it into the code.

    As a placeholder, I’d been using a block from the WordPress repository called simple-alert-blocks. The simple part of the name doesn’t mislead. Nothing wrong with that, but it doesn’t fade.

    So I thought, I’ll add Cursor to make changes to it so that it always disappears after ten seconds.

    Only too happy to oblige

    Cursor happily did all this–it even looked pretty good as code, just scanning over it–and it didn’t work. Absolutely nothing happened. I started by asking it to debug the problem and it happily provided me with a “fix,” except that the fix simply re-applied code that was already there. So this improved nothing.

    I took a few minutes to look at it, but wasn’t seeing the problem. Later I realized that it had probably created a mismatch between the class name it was applying to the message box and the class name it was using in the css file. The class in the css file was .wp-block-pz-alert whereas the actual element in the DOM was using .wp-block-create-block-pzalert.

    I say this was most likely the problem because I didn’t have the code by the time I figured it out, but that CSS mismatch was a theme throughout the whole process.

    Keep your context ungoofed

    Leading to another takeaway: if Cursor does something substantially screwy, don’t just fix the problem, reset your context so that it isn’t still chewing away with the wrong idea in the back of its mind somewhere.

    So then I asked it to just create a block that did what I wanted from scratch. This one also looked pretty good, but wasn’t registering the block once I’d activated the new plugin (for once I didn’t forget the activation step). Again, strong suspicion that the mismatched CSS was in play, but there was also some idea that I’d inadvertently introduced because the original simple alert box was still in context that there should be a separate .JS file that had a “fade” function in it rather than just including this in the view.js file.

    Doublechecking

    At this point, I decided to take the AI part in far smaller steps and now created a new block using the create-block script. From there, I asked for specific steps and checked that each step worked. It occurs to me that Cursor currently makes about the same number of mistakes as I do, so I should doublecheck my progress in more or less the same way.

    This doublechecking process eats away at the time advantage of having Cursor just blast out a whole plugin, but is still way faster than my usual process. This is in part because it remembers all the function definition and syntax details that I routinely forget. It’s massively more capable than the sort of autocomplete you get with something like Github’s Copilot.

    Even in this process, it fouled up the CSS again. But it did lots of other things–using details that are very specific to WordPress block development–and had no difficulty with it.

    I asked it to add an attribute to the block, one called “messageText”:

    Note, though, that it decided to freelance on the “name” attribute. I did not tell it to create a pz domain and there were lots of other blocks in context that do it the way I wanted it, so conceivably it might have figured it out.

    Anyway, adding the attribute worked just fine, but in typical computer fashion, there were plenty of obvious related tasks that I had to specifically ask for.

    Initially, the suggested changes didn’t include importing the TextControl component, so it didn’t work and this is one of those problems that doesn’t really throw any errors, it just quietly refuses to register the new block.

    I asked it to fix this and it replied with the cheery bullshit one sometimes gets from LLMs:

    And then the line was there. But you have to wonder…

    Anyway, when I really got down to brass tacks and was explicitly asking it to make changes in chunks that I could quickly doublecheck, the process went quickly. It would have gone even quicker if I’d reset the chat and started with fresh context.

    More reports from the coding trenches to come…

  • Adding Logic Cleanly

    With the WordPress block editor, you get a reasonably good editor for managing the pieces that make up a typical web page. And that can include things like forms and interactive charts and so on.

    For that reason, PeakZebra uses the block editor as the interface for any clients that want to build or customize their own pages. They are otherwise shielded from the potential confusions of the WordPress back end.

    But while the block editor is good for making a page that looks like part of an application, you have to ask the question: what happens when something is supposed to happen.

    Enter logic

    For “normal” form processing, PeakZebra justs handles putting any updated values from forms on the page into their appropriate database records. For use cases where you’re just tracking data (what’s this client’s mailing address?) that’s surprisingly powerful all by itself. If you use address fields in a form that gathers client information, for example, simply submitting that form ensures that the data winds up stored in the right table.

    But what’s needed beyond that is a (relatively) easy way to make more complex interactions happen. I think what you need is some kind of logic block that’s configurable in the editor–you give it a set of instructions through some kind of GUI–and presumably not visible (though present and ready to do its work) in the front end.

    Alternatively, you could simply make it possible to attach actions or code to each element of a form or other block and tie them to specific actions (onclick, for example), in pretty much the same matter that HTML lets you attach JavaScript to element events.

    The lotsa-pulldowns approach

    While Bubble and other no-code platforms use a sort of “assemble instructions by clicking options” approach to attaching procedures to elements, I’m resistant to this, even with a client base that doesn’t really want to code.

    That’s because it quickly becomes nearly impossible to keep track of what’s going on (or what’s going wrong) because you have to go back through all the options you selected in that visual interface, plus you can’t get any coherent overview of your whole application’s logic flow. (Actually, maybe one or another of the no-code options handles this well–I’d love to get a heads up on that.)

    So it’s tempting just to make it easy to insert plain old code snippets into a logic block that essentially just exists as a container to put that code in. This, of course, means people have to code at least a little in order to take advantage of this.

    One ecosystem divided by two languages

    In the WordPress world, this approach gets more complex right out of the gate because, of course, WordPress uses two separate languages: PHP on the server and JavaScript on the client side. So should the logic block handle one or the other, or both. And does this increase the complexity sufficiently that this just can’t be termed “low code” anymore.

    I’m tempted by the idea of creating a highly-simplified language for describing what should be done, like:

    see if zipcode begins with “19”

    if yes, set timezone to “EST”

    And then this would parse back into _either_ JavaScript or PHP, as appropriate. Sounds so easy, right? What’s a programming language but a huge nested if statement, amirite?

    Let’s be real, or else let’s use AI. It’s magic.

    Sure. However. Given that this is almost certainly way harder than it sounds and would be a constant source of annoyance while the kinks were ironed out, I then begin to wonder whether AI is the answer. It’s the answer for everything else, after all.

    And this actually does seem plausible, given how good copilot style programming assistance AI has gotten. You’d just need to train the AI on the specific codebase, something that Cursor does already, though I haven’t tried it yet to see if it actually “gets” a WordPress code base.

    But I don’t think, for the moment at least, that AI is really the answer. And that’s because experienced developers bring some important horse sense into the game.

    Horse sense to the rescue

    It’s pretty easy to design a system that does something that is error prone and non-scalable from the get-go. If you talk to a developer who really understands the code base and what you might be trying to do with it, they can help you see if you’re really tackling the problem in the right way, with the right approach.

    In other words: maybe you could get the count of the number of tasks associated with a project by counting the tasks associated with that project in the task table, but maybe it’s better to keep a running total that the system updates whenever tasks are added or subtracted from the project.

    You want someone at least looking at this from a perspective that has the whole picture in view.

    For the foreseeable future, this is how PeakZebra handles these things: by request. Your request to do X or Y is handled by a real, human programmer who is familiar with the PeakZebra code base as well as the WordPress platform (from a technical perspective).