Hey guys, this week was also about making the CRM feel more complete. Alongside several new features, I also spent a good amount of time improving security and fixing one particularly deceptive bug.
First of all, I added a new global Calendar page that shows every record with a date in one monthly view.
Events, tasks, reminders and subscription renewals are all displayed together, each with its own color. Before this, the calendar only existed inside each record type, so there wasn’t a way to see everything happening at once. I also integrated Cal.com. The booking page can now be embedded directly inside the CRM, and when someone books a meeting, a webhook automatically creates an Event record. If the meeting is rescheduled, the existing record is updated instead of creating a duplicate, and if it’s cancelled, the event is removed.
To keep the integration secure, the webhook signature is verified using the raw request body instead of reserializing the JSON.
I spent some time looking at features from Pipedrive, HubSpot and Attio, then implemented a few that I really liked. The Kanban board now shows the total value of each column, making it easy to see how much every stage of the pipeline is worth. I also added rotting, which highlights cards that haven’t been updated for more than two weeks so forgotten leads are easier to spot.
Another big addition is public forms. Every record type can now expose a public form that can be shared with a link or embedded into any website. When someone submits it, a new record is created automatically and any related workflows are triggered. The feature also includes a honeypot for bots and per-IP rate limiting. Finally, I added a Trash Bin, allowing users to restore accidentally deleted records with a single click. I also added the ability to assign an owner directly from the record page.
Passwords now follow the same rules everywhere in the application:
- at least 8 characters
- one uppercase letter
- one lowercase letter
- one number
- one special character.
The backend enforces the policy, while the frontend shows a live checklist as the user types.
I also added a Change Password page. When a password is changed, every other active session is logged out while the current one stays active.
At one point login stopped working and always returned “Invalid credentials”. It turned out the password wasn’t the problem at all, the backend was stuck in a crash loop.
A new database column was added as “not null” without a default value, so Hibernate couldn’t apply the change to an existing table. The application never finished starting, and the frontend showed a generic login error.
I fixed the database manually, added a default value to the migration, and made a note for the future: every new “not null” column should always have a default value.
After adding all these features, I went through another security pass. The rate limiter now also protects password changes and the Cal.com webhook. I also added a scheduled cleanup job that removes old expired sessions from the database.
Finally, I configured proper security headers, including a CSP. Public forms can still be embedded on external websites, while the rest of the CRM remains protected from being embedded elsewhere.
Stay tuned, cause I still have lots to do :)
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.