Book sharing system
This section explains what the book-sharing system does, how the main content fits together, and how members move through it.
At a product level, the system supports four things:
- keeping a clean shared book catalog
- letting members track their own reading activity
- letting members publish reading updates and thoughts
- letting other members respond with comments and reactions
We designed it this way because book sharing is not just one kind of activity.
- Some content should be stable and reusable, like books and authors.
- Some content is personal and changes over time, like a reading journey.
- Some content is lightweight and social, like a reading share or reaction.
If all of these were stored as one generic "post" model, the system would be easier to start but harder to govern later. Search, moderation, visibility rules, and analytics would all get messier.
The important split underneath that is this:
- Directus collections define the shape of the data.
- Directus relations define how records connect and what happens on delete.
- Directus flows block bad writes and auto-fill ownership fields.
- The app layer still handles some read filtering, especially
share_author_onlycomment visibility.
That split is deliberate.
- The CMS is good at storing structured content.
- Relations are good at keeping connected records consistent.
- Flows are good at enforcing cross-record rules.
- The app layer is still the best place for nuanced viewer-specific read decisions.
At a glance
| Area | Main collections | Why it exists |
|---|---|---|
| Book catalog | books, authors, book_authors |
Stores canonical book and author records |
| Reading activity | reading_journeys, reading_shares, reading_share_images |
Stores a member's personal reading progress and share posts |
| Comments | reading_share_comments, reading_journey_comments, book_comments |
Stores user-written discussion content |
| Reactions | reading_share_reactions, reading_journey_reactions, book_reactions |
Stores one-like-per-user interaction rows |
How a member experiences it
Most members will move through the system in a simple loop:
- discover a book
- start a reading journey or post a reading share
- update progress or thoughts
- get replies or reactions from others
That makes the system feel social, but the model underneath is fairly strict. Books are the stable public reference point. Journeys and shares are personal activity records. Comments and reactions hang off those records.
We chose this split to avoid mixing editorial content with member activity.
- A book should stay the same no matter who is reading it.
- A reading journey belongs to one member and one reading process.
- A reading share is a publishable moment inside that process, or sometimes outside it.
This keeps the public catalog clean while still letting the community be expressive.
System map
flowchart TD
A[authors] <-- M2M via book_authors --> B[books]
B --> C[reading_journeys]
B --> D[reading_shares]
C --> D
D --> E[reading_share_comments]
D --> F[reading_share_reactions]
C --> G[reading_journey_comments]
C --> H[reading_journey_reactions]
B --> I[book_comments]
B --> J[book_reactions]
D <-- M2M via reading_share_images --> K[directus_files]
U[directus_users] --> C
U --> D
U --> E
U --> F
U --> G
U --> H
U --> I
U --> J
Core user flows
1. Browse a book and join the conversation
flowchart LR
A[Member opens a book page] --> B[Reads book details and linked authors]
B --> C[Views public comments and reactions]
C --> D[Adds a comment or reaction if the book is published]
This is the simplest flow in the system. The book acts as the public anchor record, and members can discuss it directly.
It is designed this way so conversation can gather around one shared reference point. If every member had their own copy of a book record, comments and reactions would fragment across duplicates.
2. Start a reading journey
flowchart LR
A[Member chooses a book] --> B[Creates a reading journey]
B --> C[Sets title, status, and visibility]
C --> D[Updates the journey over time]
D --> E[Receives public comments or reactions if the journey is public]
Reading journeys are for longer-running reading activity. They connect one member to one book over time.
This exists because not every reading update should become a public post. A journey gives the member a persistent place to track progress, status, and context even when they are not actively publishing shares.
3. Publish a reading share
flowchart LR
A[Member writes a reading share] --> B[Links it to a book]
B --> C[Optionally links it to a reading journey]
C --> D[Adds text and images]
D --> E[Publishes the share]
E --> F[Other members can comment or react if it is public]
Reading shares are more like posts. They can stand alone or sit inside a longer reading journey.
That flexibility is intentional. Some members want to post a quick thought without maintaining a full journey. Others want a series of shares attached to one reading timeline. The model supports both without forcing one behavior.
4. React safely to someone else's content
flowchart LR
A[Member clicks comment or react] --> B[System checks target state]
B --> C[System assigns the acting user automatically]
C --> D[System blocks invalid or duplicate writes]
D --> E[Interaction is saved]
This is where the Directus flows matter most. The user experience stays simple, but the backend makes sure the interaction is allowed and correctly attributed.
We designed the interaction path this way so the client can stay lightweight. The frontend does not need to be trusted with ownership or moderation logic, which reduces the chance of accidental or abusive writes.
What the system is trying to protect
The design is mostly about keeping user-generated content trustworthy.
- Users should not be able to pretend to be someone else.
- Users should not be able to comment or react on targets that are private or not meant for interaction.
- Users should not be able to create duplicate reactions on the same target.
- Deleting a book, journey, or share should clean up attached interaction rows automatically.
- Deleting a user should not wipe out the rest of the conversation history.
Main content types
| Content type | What it represents | Typical owner |
|---|---|---|
| Book | A canonical shared book record | Editorial or managed content |
| Author | A canonical author record | Editorial or managed content |
| Reading journey | A member's ongoing reading record for one book | Member |
| Reading share | A member's post about reading progress or reflection | Member |
| Comment | A member's written response to a book, journey, or share | Member |
| Reaction | A member's lightweight one-like response | Member |
Why the model looks like this
The system does not treat everything as a generic post.
- Books stay clean and reusable across the platform.
- Reading journeys capture a longer story around one book.
- Reading shares capture smaller moments, updates, or reflections.
- Comments and reactions stay attached to a specific target, which makes moderation and visibility rules much easier to reason about.
That is the main design idea behind the whole system: stable reference content at the top, personal activity in the middle, and social interaction at the edge.