:THREAD :INFO Four Things at Four Different Stages Reactions, comments, follows and notifications get described together as a social layer, which flatters three of them. They were built years apart, they have very different amounts of finish, and pretending otherwise would make this page useless as a reference. So: in order, best first. :STATS :INFO Reactions Attach to Chips Love, Applause, Fire, Insight, On point. They land on a single chip rather than the page, so a slate with twelve chips has twelve independent reaction bars and the shape of the response tells you which part landed. The bar is hidden entirely at zero and while editing, so an empty page stays quiet instead of showing five grey zeroes. :INFO Not a Radio Button The uniqueness constraint is on the triple of chip, user and reaction type, not the pair. One person can leave all five on the same chip. That was a choice: a reaction here is a note about what the chip is, not a single vote, and something can be both funny and useful. :CODE [language:java] @Table( name = "chip_reactions", uniqueConstraints = @UniqueConstraint(columnNames = {"chip_id", "user_id", "reaction_type"})) :INFO Nothing Is Counted Twice There is no counter column anywhere. Totals are grouped on read, and a whole page of reactions comes back in one query rather than one per chip. It costs a little at read time and it means the number is never wrong, which for a feature nobody audits is the better trade. :INFO They Survive a Republish This is the part worth stealing. When a slate is pushed again from a repository the chips are rebuilt from scratch, which would normally orphan every reaction. Instead, old and new chips are matched by their row and position in the grid and the reactions are re-pointed. Edit a typo on a chip that thirty people reacted to and the thirty stay. Building that was slower than not building it, and it is the difference between a feature people trust and one they learn to avoid. :INFO Follows Follow Slates There is no user-to-user follow anywhere in the codebase. You follow a slate, which suits a platform where the thing worth tracking is a project rather than a person. The endpoints work. The follow and unfollow hooks on the front end are fully written and have zero call sites, so there is no button to press. The feed that would list what you follow is one repository method that nothing calls. :INFO Notifications Are Half a Loop Three events write a notification: someone follows your slate, you get invited to one, you get a message. Reactions and comments write nothing, though the enum has values for both. The seen timestamp exists on the record and is never set by any code, so the unread count only ever goes up. The screen that would render them expects a title and a body the server does not send, and it is not imported by anything, so it has never been on screen. Written path partly alive, read path not built. :CHECKLIST Where the four stand today [x] Reactions: shipped and in use [x] Reactions survive a republish [x] Comments: post and upvote [ ] Comments: edit delete or report [x] Follows: endpoints live [ ] Follows: a button anywhere [x] Notifications: written on follow invite and message [ ] Notifications: marked as read [ ] Notifications: shown to anyone :INFO Why Publish the Gaps Because the alternative is a page that reads like a feature list and teaches nothing. The interesting content in a social layer is not that it has reactions. It is that reactions were built to survive a rebuild and notifications were not finished, and that both of those are true at the same time in a product that ships. :QUOTE [quotetype:plain] Three of these are features. One is an enum with good intentions.