Circa banner

Circa

17 devlogs
81h 9m 28s

Event-based management app that's designed to help you organize cool initiatives and not worry about creating another account you won't use ever again! Open source, pretty and privacy-first :3

Most event tools try to become a permanent system o…

Event-based management app that’s designed to help you organize cool initiatives and not worry about creating another account you won’t use ever again! Open source, pretty and privacy-first :3

Most event tools try to become a permanent system of record. Circa is meant to appear when an event needs structure, help the team run it, and disappear when the job is done.

This project uses AI

Unit tests and mock data were created using AI. It was also used to speed up the creation of boilerplate code (there’s quite a bit of it in typescript and Rust 😭). Later on AI was used to introduce changes that would otherwise require tedious ctrl+c ctrl+v work in tens of files at once.

Demo Repository

Loading README...

grm

Shipped this project!

Hours: 81.16
Cookies: 🍪 2095
Multiplier: 25.81 cookies/hr

It’s alive!! The demo is now available The ship is officially… shipped :3


Login is passwordless, because passwords are booooriiing x3 The app uses magic links instead: enter one of the demo emails, request a link, then use the generated magic link to sign in.


Demo accounts:


Once you’re in, the best event to start with is the big launch summit. It has the most complete demo data: collaborators, branding, planner timeline, assigned work, unassigned work, socials, lifecycle state and enough timeline chaos to actually show why the app exists x3


The main things to try:

  • open an event and check the overview/lifecycle panel
  • look at the planner timeline and move/edit some scheduled work
  • check the staff page to see workload and unassigned tasks
  • open collaborators to see roles and event access
  • try the socials tab and update post statuses
  • play with branding if you want to make the event look cursed or cute
  • export an event if you want to see the current event data bundle

The demo database resets automatically, so don’t worry too much about breaking things. In fact, please break things a little. That is kind of the point x3

This is still an early version, but it’s finally public-demo-shaped now. The app is real enough to click around, test the concept, and see where the event-ops idea is going.

grm

This one’s just README adjustments and making sure the demo environment is healthy and working as intended :3 Coming very soon -w-

Attachment
0
grm

Most of this update was demo polish. I replaced the tiny dev seed with actual demo data. There are proper test users now, multiple events across different lifecycle states, real-looking memberships, branding, planner items, timeline work, assignments, unassigned queues, social drafts, posted posts, blocked tasks, the whole thing. The demo finally has enough stuff inside it to show what the app is supposed to be, instead of me clicking around an empty shell x3


The staff/planner side especially needed this. A workload dashboard is not very convincing if everyone has one fake task and nothing is blocked. So now the seeded events have enough scheduled work to make the timeline scroll, enough assignments to make staff cards useful, and enough unassigned items to show the flow. I may have slightly overfed the demo data creature, but honestly it needed food x3


There were also a few last frontend fixes. The sidebar now shows the real event ID even when the URL uses the slug, because the slug URL work made that little corner weird. The planner timeline got another pass so the grid behaves better when there is more data, milestones sit in their own row more cleanly, and the controls do not feel like they are floating off into… I don’t even know where they were going QwQ Also, owner is now a dropdown instead of a free-text field, because free-text owner names were useful for scaffolding and kind of silly for the actual demo.


Tests got fixed again too. I wish they would stop needing emotional support, but here we are. At least I didn’t have to correct them manually. The important part is that the suite is back in line with the current codebase.

Root deploy state was updated as well, so this is basically the demo deploy build. Not the fully public release yet, but the version that should be shown is assembled now.


So yeah, this one is not about adding a new tab or a new module (what a shame!!). It is about making the demo stop feeling like a dev environment and start feeling like a thing I can actually hand to people :3

Which is scary…

But also. Finally @w@

Attachment
0
grm

I did a UX pass across the frontend. Sanding down a lot of sharp edges that became very obvious once the app was running somewhere real xC Cards feel more clickable now, navigation has clearer active states, buttons/selects got a bit nicer, loading states have an animated thingy, empty states are less awkward, and there are icons in places where the UI needed a tiny bit more direction instead of just text everywhere :3


The biggest actual quality-of-life thing is toast notifications!! A bunch of actions now give proper feedback instead of silently succeeding and leaving you wondering if something’s wrong… Creating events, saving branding, managing collaborators, changing planner items, moving/expanding timeline blocks, updating socials, exporting, lifecycle actions, etc. now produce little success messages. Very basic, but it makes the app feel way more alive and less prototype-y >w<

There was also a bunch of small visual motion/interaction cleanup. Hover states are smoother, clickable surfaces are clearer, badges and alerts got icons, the select component finally looks presentable and there’s a shared loading primitive now instead of each page improvising its own “Loading…” text x3 Tiny stuff, but it matters a lot QwQ


Backend got a couple of practical fixes too. Magic-link emails are normalized to lowercase now, so logging in doesn’t randomly fail because of email casing (insane how me testing on the same email made me miss this for so long…) Event creation validation is stricter as well: slugs have better rules (and are validated at all… or will be in the near future!), timezones are validated as real IANA timezones and events can’t be created with an end date already in the past. There’s also a slug availability endpoint now, which should make the event creation flow nicer once the frontend uses it properly.


So yeah, this is mostly post-deploy polish. Still private, still needs a few more passes, but this was a good cleanup round :3

Attachment
Attachment
Attachment
0
grm

New version is deployed, although not publicly available yet. So it’s not a full release-release, but it’s there!


The big frontend migration is finished now!! The primitive/component cleanup that was still in-progress last time is done: the old base components got removed, the new UI primitives are the actual direction now, and the dashboard views are much less messy internally. There are shared surfaces, link-buttons, panel headers, status badges, role badges, form options and all those tiny repeated pieces that were previously duplicated across cards!!!


There’s also a proper logo/favicon now! Tiny thing, but it matters to me…


On the deployment side: the root project is now set up (almost?) fully. The Docker build uses Node 24 for the frontend, builds the frontend, builds the Rust backend, then ships the built frontend as static files from the backend.


So yeah, to sum it up: migration finished, private deploy exists, the app is much closer to being shown to people (you are the people!!). Next up is readmes, test accounts, ship/guide text, then making it public when it’s ready. That moment’s getting closer and closer @w@

Attachment
0
grm

Okay so, this one is mostly about making the app deployable. In the meanwhile (as always…) I’ve noticed many things that can be done in a better way, so this one is deploy + those (they’re still in progress tho…)


The backend got a pretty serious round of cleanup and hardening. API routes are now properly scoped under /api, which fixed the 404 situation, and the frontend/backend dev setup is cleaner now too. Vite proxies API calls in development, while production can serve the built frontend directly from the backend. It works. Finally QwQ


I also added configurable ports, production/local database behavior, and a seed reset flow for the demo database. The app now resets from seed.sql on startup and periodically after that, because this is a public-ish demo and someone will absolutely delete everything the moment they can. I respect the chaos, but the database now fights back >:3c


There was also a lot of schema and seed cleanup. The local/dev database now matches the newer event/planner/collaborator/socials shape better, and the seed data is kept usable for the dashboards (thanks to GPT!). Very boring sentence, very important change.


Tests also expanded a lot. Backend tests now cover much more of auth, users, events, routes, services, config/db behavior and delivery logic. Frontend tests got a big pass too: primitives, dashboard components, planner timeline pieces, socials, staff, collaborators, composables, router behavior, and view-level flows all got more coverage. Also thanks GPT! I would’ve never done this by hand in less than 100 hours 😭


On the frontend side, the planner refactor from the previous cleanup wave has now landed properly. The timeline board, creation panel, item form, and item list are split out and the dashboard itself is much less of a giant file. There were also styling fixes around the planner, Vite/auth cleanup and more small adjustments after the component migration.

In-progress

I’m still doing component cleanup around repeated status badges and little UI inconsistencies. Event statuses, planner statuses and social post statuses are being pulled into dedicated components instead of every card inventing its own mapping. There’s also some deploy/readme/runtime cleanup happening around Node 24 and the Docker build. So the next bit is basically polish the remaining visual/component stuff and finish the last cleanup pass. The deploy is done, but not fully available to public. It will be in a short time… (because FT is ending soon QwQ)

Attachment
Attachment
0
grm

This one is almost entirely frontend. It was pain. I persisted!! The UI refresh that’s been looming ominously in the distance has finally started landing for real @w@


I introduced a proper UI primitive layer, so the app is no longer relying on every dashboard hand-rolling its own slightly different buttons, panels, fields, inputs, badges, alerts, empty states, etc. There are now shared components for the common building blocks, plus cleaner themes and a flatter visual language. The old glowy glass chaos is being slowly bonked into something more consistent and usable QwQ


A lot of the existing dashboards got broken apart into smaller components. Events, event details, branding, socials, collaborators, staff, and the planner are no longer untamable giants. They now have dedicated forms, cards, panels, previews, rows, workload lists, timeline boards, timeline forms and so on. Functionally this does not sound as exciting as a shiny new feature, but it makes the app way easier to keep building without every change turning into frontend archaeology x3


The planner also got pulled into this new structure. The timeline board, item creation panel, item form, and timeline item list are now separate pieces, and they use the shared primitives too. So the Gantt/planner area should be much easier to polish and extend now, especially since it already has collaborators, assignees, statuses, colors, and scheduling all trying to coexist in one place like a tiny operational hydra (hydra would be such a cool expansion to aether btw…) :3


The app shell itself changed too: cleaner desktop sidebar, better mobile navigation, less background noise, flatter surfaces, stronger spacing, and consistent theme variables. It’s still not perfect, but the direction is finally becoming coherent. Yippee for me! x3


So yeah, this is mostly a structural + visual cleanup update, but a pretty important one. The near-future plan is now clear: polish the remaining visual inconsistencies, make sure the refreshed UI feels good across the app, and then finally deploy. Terrifying, but we are getting there x3


Before the deploy I will need to go through the security flows and check if nothing’s dumbly exposed. Wouldn’t want someone to take this pretty creation down… :C

Attachment
Attachment
0
grm

A tiny one >w< I added a Staff dashboard! It pulls event collaborators and planner timeline items together, so you can see the team, how much work is assigned, what’s blocked, and which timeline items still don’t have anyone attached to them! Each person now gets a little workload card with their assigned items, open/done/blocked counts, contact info, and timing windows. You can instantly see who’s slacking off x3 It’s still pretty basic, but the important thing is that it connects the systems that were previously separate: collaborators, roles, assigned timeline work, and blocked tasks. This means it’s actually becoming a complete, end-to-end (another word for complete… x3) system for tracking events! yippee!!


Also, in-progress: the big UI refresh has started :3 It’s not shipped yet, but the direction is finally moving away from the glowy glassy chaos (which I love, but didn’t fit the purpose of this system at all :c) and toward a cleaner primitive-based UI system. I started laying down reusable components like panels, buttons, fields, badges, alerts, page headers, selects and inputs, plus a flatter theme setup and refreshed desktop/mobile navigation. Below are some pre-release teasers into how it’ll look ;3


Also a disclaimer: the test/mock data is AI generated. This means the layout and other stuff are made by a real caffeine-fueled human, but the text and stuff is not!

Attachment
Attachment
Attachment
0
grm

Events finally have proper collaborators now! There’s a Collaborators page where event owners can manage the team for an event. For now it works with existing users: you add them by email, pick their event role (owner, organizer, staff, or volunteer), see their contact info, update their role, or remove them from the event. Non-owners can still see who’s involved, but they don’t get the fun buttons x3


The backend permissions also got tightened a lot. Accessing the event is no longer the same as modifying everything inside of it now! The role system is still very much evolving, but it’s there, so that’s progress :3


The planner got tied into this too!! Timeline items can now be assigned to actual event collaborators. The frontend loads the event team into the planner form, lets you pick who a timeline item belongs to, shows the assigned person on the chart, and the backend verifies that the selected user really belongs to that event. So the Gantt thing is no longer just a rectangle with text :3 (okay honestly it still kind of is, but let’s skip over that part for now!)


Also fixed a couple of small but annoying things while wiring this together, including the social status dropdown not reflecting the current status properly and a timeline duration math oopsie that could make bars not behave… Tiny fixes, sadly (or not!) more to come!

Attachment
Attachment
0
grm

Usability update! After getting the Gantt planner to exist last time, I went back and started making it less of a prototype… Planner timeline items can now be edited more properly instead of… not that. You can change their title, type, dates, status, owner, color and notes, plus shift items around in time and resize them a bit. It’s still not the final dream planner by any means, but it’s already getting a lot closer!


The Socials tab also got a much-needed pass!! Previously you could create posts and move their status around, but now drafts can actually be edited after creation. So if I typo the platform, title, body, or status, I don’t have to delete the whole thing and pretend that was intentional!! how cool x3


The other big thing is branding becoming properly interactive :3 Backend branding data now has more theme fields, like theme mode and background color, and the frontend can actually apply event branding to the app shell through CSS variables. So changing colors in the Branding tab can affect the event workspace instead of just living in a preview box forever. Excitinggg x3


And because all of this was starting to cause way too many repeated fetches and stale UI moments, I added a local frontend cache for event data. It caches event details, branding, planner items, timeline items, social posts and exports, refreshes things in the background, and invalidates the right pieces when mutations happen. It’s not fancy distributed systems magic or anything, but it makes the app feel snappier and way less twitchy. You have to trust me on this one, but it was really needed xC

Attachment
Attachment
0
grm

Yesterday the event workspace started feeling a lot more complete, but today is where the planner started becoming a real planner x3 The Socials tab is now properly usable: event-specific social drafts can be created, passed through statuses and removed when needed.


I also added more of the event lifecycle/ephemeral-event stuff (you know, the core… at least we’re getting there!)!! Events can now be archived, and there’s a JSON export flow that collects the event, branding, planner items, social posts, and timeline planner data. This is pretty important conceptually, because the app is supposed to care about events ending, being cleaned up, and not just living forever. So now there’s at least a real path for take your data and go :3

But the most exciting part is definitely the planner work! The old planner was basically a cute little TODO list, and now it has the start of an actual Gantt-style timeline!! It is still a little wonky, and I already know there are things I’ll need to clean up, but it exists!! The scary (for me, okay? x3) part is finally turning into code >:3c


So yeah, this feels like one of the more meaningful updates so far. Socials are usable, export/archive support the whole ephemeral concept, and the planner is no longer just a list pretending to be a plan. There’s still a lot of polish ahead, but today made the app feel way closer to an actual event operations tool QwQ


(yes, it’s still in development, hence the weird styling - it will get resolved once the functionality is fully in place QwQ)

Attachment
Attachment
Attachment
0
grm

A big one!! I spent a lot of time pushing the event workspace forward, and it finally feels less like a bunch of disconnected panels and more like an actual event-centric app. The sidebar got redesigned, the mobile nav got overhauled, the routes make a lot more sense now, and once you’re inside a specific event you can actually move around that event’s own space. I know, woahh,, It’s a pretty major structural improvement, even if a lot of it is still basic MVP functionality

Currently implemented bits are roughly:

  • Planner - I added the basic planner flow end-to-end! There’s now backend support for planner items, plus a frontend planner dashboard where items can be created, checked off, and removed. Still pretty minimal, but at least real now!! :3
  • Branding - Basic branding functionality is in too!! There’s now backend support for event branding records, and the frontend has a proper branding screen with event name override, tagline, primary and secondary colors, notes, and a live preview. I may or may not have played with the preview for a bit too long… >:3c
  • Navigation and overall structure - I reworked the app into an event-workspace shape instead of whatever the old situation was. Desktop and mobile nav both got cleaned up to reflect that (they’re still very rough, please bare with me QwQ)
  • Event flow polish - I also cleaned up the event hub/routing side of things so creating an event and dropping into its workspace feels way more natural. It is still very buggy and the UI just kind of… broke… (I promise I’ll fix this once everything is functional 😭) (there’ll be a sizeable design overhaul in a bit, after all the main flows are complete)

The planner exists, branding exists, the app structure finally makes more sense, and the whole thing feels a lot closer to an actual usable system instead!!! Hopefully it’ll become just that in the near future x3

Attachment
Attachment
0
grm

A smaller one. I spent this session rethinking the frontend navigation a bit, because the old flat dashboard setup was starting to feel really wrong? It technically worked, but didn’t really match how I want the app to be… So I started reshaping things around events instead of treating every panel like some unrelated entity. Events is now the real entry point, and I split out a separate event-section model for things like Overview, Planner, Branding, and Socials so the structure can revolve around a specific event rather than just dumping a pile of dashboards into the sidebar and calling it a day (yeah it did kinda be like that…)


So yeah, this one is more of an architecture/UX pass than a shiny flashy feature update, but I think it matters a lot. I cleaned up the route and section config, started stripping away some of the old top-level dashboard baggage, and generally nudged the app toward a much more event-centric shape (as intended!!). It’s still mid-transition and not fully wired end-to-end yet, but the direction already feels way better, more like a coherent app x3 No huge feature boom today, but definitely one of those quieter refactors that’ll make the next changes much less cursed in the future x3

Attachment
0
grm

Finally made the whole passwordless auth flow complete. Up until now, magic links technically existed, but actually using them for testing still felt kind of silly and awkward… so I implemented a proper delivery/outbox setup for them! There’s now a test inbox flow, which means I can request a magic link for a “tester” account and then fetch the latest still-valid one from a dedicated dev inbox instead of digging through the backend terminal x3 Considering how unusual the no-password setup is, this helps a lot 😭


I also tightened up the auth flow itself while I was there >:3c Requesting a magic link now returns a generic response instead of basically snitching on whether an email exists, and once a link is used, both the token and its inbox entry get marked as used properly. I also made the backend initialize the relevant schema on startup, because apparently “surely the table is already there” is not, in fact, a valid architectural principle x3 So yeah, the flow feels a lot more real now, and a lot less held together by hope alone


On the frontend side I gave the auth screens a much nicer pass too!! Public routes now get their own layout, the login panel looks way more intentional (and kind of AI generated, which pains me because I love glassmorphism so much 😭), there’s a dedicated dev inbox view, error handling is less janky, and the overall styling/background situation feels a lot cleaner and less placeholder-like. I also had to go back and adjust a bunch of backend and frontend unit tests to match the new behavior (well, when I say I, I really mean Opus…), but honestly that was overdue anyway.


So overall: magic links now have somewhere tangible to land, the tester flow is way less annoying, and the whole auth system feels a little less embarrassing and a little more like a real feature :3

Attachment
Attachment
0
grm

Long time no see! (again…)


The auth/roles mess I was talking about last time has finally started turning into an actual system instead of just a pile of question marks and wishful thinking x3 I sat down and reworked the permission model properly, so the placeholder silliness is gone and the app now has actual roles: Admin, Organizer, Staff, Volunteer (farewell Clown… you were iconic, but you had to go 😭). I also wrote out some proper role/permission docs, mostly because I was getting tired of re-conceptualizing the entire app every 5 minutes QwQ

The unusual nature of this project (ephemeral, passwordless, etc.) is still being a menace, but I finally have something real working!! I ended up going for a magic-link kind of flow: submit email -> get a one-time token -> verify it -> receive a JWT -> use that to access protected routes. So the whole “how do I auth people without just letting them spoof each other for fun” problem is, thankfully, no longer completely owning me >:3c (it is still somewhat problematic tho…) The user module got tightened up a lot too: routes are now protected with JWT middleware, update/delete finally respect who the caller actually is, there’s user lookup by email for auth, and I added support for stuff like availability hours. Also made a small seeding/setup flow for dev data because manually poking SQLite every time was beginning to wither my soul x3


And!!! the frontend is finally participating in society instead of just standing there looking pretty :3 There’s now an actual login panel, magic-link verification, logout, route guards, role-based navigation, and proxying so the frontend and backend can talk to each other without weird hacks or ritual sacrifice. I also went back and expanded (or rather fixed…) the tests, because last time I had that whole “there are tests!!! (they’re dying)” situation 🥀 Backend coverage is in a much healthier place now, and I even added frontend unit tests for auth, navigation, routing, and the login flow. There’s still a lot to polish, and this weird little passwordless creature of an app continues to humble me daily… but it finally feels (somewhat) like progress :3 (there’s still so much to do 😭)


(I know it’s not pretty yet but I’m really trying, okay? QwQ)

Attachment
0
grm

Slowly and painfully, but we’re getting somewhere! I’ve started implementing the backend. Couldn’t hold myself back anymore, the UI can wait x3 I chose the Actix + SeaORM + JWT middleware way of doing this, because I’ve never used Actix or SeaORM before, and have heard good things about them from my friends! I have to agree that it’s an amazing stack: everything’s structured, modularized, but still monolithic in nature (microservices are eww). I am also having a blast learning all the cool Rust-native mechanisms that these offer.


The unusual concept of this app (it’s ephemeral nature, no passwords, etc.) is starting to pose a real challenge, and so many problems are beginning to arise QwQ But I know I will get through no matter what!! Even if I don’t do them the best way, it’ll be an invaluable learning experience!!! hopefully x3


Currently implemented a basic user module and authentication scaffolding. At the moment I’m in the process of laying out documentation that will (hopefully…) help me conceptualize roles and permissions, because they’ve become quite a mess… (there’s still a placeholder Clown role 😭). So yeah, goals for the near future: brainstorm the correct auth roles, add a way to add “label roles” (the ones you see, but which don’t really do anything else x3), figure out a way to auth without spoofing other users (I’ve been thinking about a challenge-response kind of thing, like the YubiKey, but I’ll cross that bridge when I get there x3). That’s a lot, but hopefully these will be done soon-ish™


Also there are some tests!!! (they’re already outdated and failing because of the JWT auth and role thingy 🥀)

Attachment
0
grm

I can’t wait until this is finished, how do you frontend bros even do this 😭


Added the staff dashboard. It’s obviously not done yet, but it gives you a basic idea of the functionality it’ll provide. This took so much time, but hopefully it’s a solid enough foundation that the future backend integration is relatively easy…


I’ve also noticed that a basic design guide would be a great thing to have now. I do have an idea of how I want this to look (even some figma designs!!), but putting this into the code is a whole another story. I’ll think about how I want to go about this later… x3


The last tab I’ll do (for now) is socials. Then, if everything goes right (it won’t), I’ll start making it actually work like a website! Yippee!! Rust my beloved please save my sanity

Attachment
0
grm

Looking absolutely horrendous. The beginnings are usually rought, but man… Progress on this is also painfully slow, as I haven’t touched any frontend code in months. Vue is amazing, but still, ughh…

Hopefully next devlog has some actual designs in it x3

Attachment
0