It's too soon after the jam for a proper post mortem, but I thought I'd write up some quick thoughts. I think some of the lessons are obvious: I spent a lot of time working on resizable web layout elements, remappable keyboard controls, and of course an elaborate character creator before making an actual game. With all of that initial polish and the dialogue that's mostly a tutorial for a game that never starts, it's inevitably disappointing when you hit the completely abrupt end. I briefly toyed with the idea of making that the point of the game: build up as much hype as possible before dropping a game over scene and promising a sequel (oh boy, oh gosh). I think that would feel like a conclusive punchline, but I didn't trust my writing ability in the early morning enough to pull off the last-minute switch.
A more subtle issue is that I never figured out how to properly structure my dialogue system and game loop and I underestimated the impact the dialogue system would have on the game loop. In my mind, the dialogue system and gameplay control were independent systems that could communicate with each other. In practice, the dialogue system IS the main game loop because game events have to be reported through the dialogue system and game events have to be triggered by the dialogue system to prevent the game from becoming out of sync with its dialogue.
When I was writing the dialogue system, I tried to make it reasonably flexible, putting in a system for substituting keywords with variables and even allowing parameterized keywords (e.g. the text "$TUTORIAL:1$" is replaced by output from a tutorial-text function with parameter '1'). I also let the dialogue system call arbitrary functions, which is extremely powerful but quickly devolves into unmanageable complexity because it's akin to relying on 'goto' statements for everything. One thing that really hurt the project was that dialogue snippets were required to specify callback functions that would ready the next bits of dialogue. There's no centralized loop at all, which is bonkers and leads to code that must contort itself to trigger events in sequence. I've never written a dialogue system before and in hindsight should clearly have spent more time learning about how they're normally constructed.
Another factor in creating a game engine from scratch is that I don't have very good tooling. Having editors that quickly reflect changes in art would be enormously helpful. Most of the art in my game is tweaked programmatically in some way, whether that's the avatar recoloring and layering, the procedural generation of playing cards, or the dynamic layout of UI. I often didn't know how things would look in the game until days after drawing the assets and my process for getting some assets into the game was incredibly cumbersome at first (I spent one afternoon manually saving dozens of layers from one drawing program as individual images, then loading them in another program to copy and paste into layers because the layers weren't being preserved between programs). I was getting better at all of this stuff towards the end of the jam, but it's been a learning experience for sure.
With all that said, if I were to do this again, I'd still try to write my own game framework instead of using a more established one. For one thing, it's fun. For another, I like that making things from scratch presents a blank slate for expression. While Unity and other engines are very cool, I always feel like they're trying to steer me towards making certain types of games. That may be because they encourage making coherent games with conventionally attractive graphics, but I think there's something to be said for the weirdness of homemade game frameworks.