Owner: Engineering Team | Last Updated: 2026-01-30 | Status: Current
The document management system stores all humanization results with full version history, drafts, and organizational features. Every time a user runs the humanizer, the result is automatically saved as a new version within a document. Users can browse, search, rename, pin, and delete their documents from the documents page.
Route: /[locale]/documents (inside the (dashboard) route group, requires authentication)
Documents follow a three-level hierarchy: Document > Version > Draft. A document is the top-level container, each humanization pass creates a new version, and users can save multiple drafts within a version.
Defined in types/index.ts.
export interface DocumentListItem {
id: number; // Unique document ID (number, not string)
title: string; // User-editable document title
user: number; // Owner's user ID (number, not string)
version_count: number; // Total number of versions in this document
version_list: Version[]; // Array of version objects
created_at: string; // ISO 8601 timestamp
updated_at: string; // ISO 8601 timestamp
}
Each humanization operation produces a version. The version stores both the original AI-generated text and the humanized output.
export interface Version {
id: string; // Version identifier (string)
input_text: string; // Original AI-generated text submitted for humanization
output_text: string; // Humanized result text
like: null | boolean; // User feedback: null = unrated, true = liked, false = disliked
action: string; // The humanization action performed
created_at: string; // ISO 8601 timestamp
updated_at: string; // ISO 8601 timestamp
word_count: number; // Word count of the output text
created_at_day: string; // Date portion of created_at (used for grouping)
history: number; // Parent document ID (number, not string)
user_id: number; // Owner's user ID (number, not string)
draft_list: DraftListItem[]; // Array of drafts saved under this version
}
Drafts allow users to save manual edits to a version's output without overwriting the original humanization result.
export interface DraftListItem {
id: number; // Unique draft ID
output_text: string; // The draft's text content
created_at: string; // ISO 8601 timestamp
version: number; // Parent version ID
}
DocumentListItem (id: number)
|
+-- version_list: Version[]
|
+-- Version (id: string)
|
+-- draft_list: DraftListItem[]
|
+-- DraftListItem (id: number)
Source: lib/store/documentsSlice.ts
{
documents: Document[]; // Array of loaded documents
next: string | null; // Pagination cursor URL for the next page (null when no more pages)
isListView: boolean; // true = list layout, false = grid layout
loading: boolean; // true while any async thunk is pending
error: string | null; // Error message from the last failed operation
limit: number; // Documents per page (default: 20)
offset: number; // Current pagination offset (default: 0)
}
| Reducer | Argument | Description |
|---|---|---|
setIsListView |
boolean |
Toggle between list and grid view. Persisted in Redux state. |
setOffset |
number |
Set the current pagination offset for the next fetch. |
resetDocuments |
none | Clear the documents array and reset offset to 0. |
Loads documents from the API with pagination support.
fetchDocuments({ token, offset, limit, pinning?, isLoadMore? })
GET /api/feature/history/?limit={limit}&offset={offset}offset === 0: replaces the documents array entirely (fresh load).pinning === true: refetches all documents from the beginning (used after pin/unpin to reflect new sort order).isLoadMore === true: appends new documents to the existing array. Deduplicates by document ID to prevent duplicates during concurrent loads.Renames a document.
updateTitle({ token, id, title })
PATCH /api/feature/history/{id}/ with body { title }Searches documents by title.
searchDocuments({ token, query })
GET /api/feature/history/?title={query}Pins or unpins a document. Pinned documents appear at the top of the list.
pinDocument({ token, id, pinned })
PATCH /api/feature/history/{id}/ with body { pinned }Permanently deletes a document and all its versions and drafts.
deleteDocument({ token, id })
DELETE /api/feature/history/{id}/| Operation | Method | Endpoint | Body |
|---|---|---|---|
| List documents | GET |
/api/feature/history/?limit={limit}&offset={offset} |
-- |
| Search by title | GET |
/api/feature/history/?title={query} |
-- |
| Update title | PATCH |
/api/feature/history/{id}/ |
{ title } |
| Pin/Unpin | PATCH |
/api/feature/history/{id}/ |
{ pinned } |
| Delete document | DELETE |
/api/feature/history/{id}/ |
-- |
All endpoints require an Authorization header with the user's access token.
Source: hooks/useDocumentActions.ts
This custom hook encapsulates all document-level user interactions. It is used by the document list and grid item components.
{
// State
isRenaming: boolean; // Whether the rename modal/input is active
isDeleting: boolean; // Whether the delete confirmation dialog is active
newName: string; // Current value in the rename input
dropdownOpen: boolean; // Whether the actions dropdown menu is open
// Setters
setNewName: (name: string) => void;
setDropdownOpen: (open: boolean) => void;
setIsRenaming: (renaming: boolean) => void;
// Actions
handleRenameClick: () => void; // Opens the rename input, pre-fills current title
handleDeleteClick: () => void; // Opens the delete confirmation dialog
handleRename: () => void; // Dispatches updateTitle thunk with newName
handleDocumentOpen: () => void; // Navigates to /humanizer?id={document.id}
handleDropdownToggle: () => void; // Toggles the actions dropdown
handleDelete: () => void; // Dispatches deleteDocument thunk after confirmation
handlePin: () => void; // Dispatches pinDocument thunk
}
/humanizer?id={document.id}, where the humanizer page loads the document's version history.session.access_token from the auth context. Operations fail gracefully if the token is missing or expired.Documents load 20 at a time using offset-based pagination. The next field in Redux state holds the URL for the next page. When the user scrolls or clicks "Load More", the app dispatches fetchDocuments with isLoadMore: true, which appends results and deduplicates by ID.
Users can switch between list view and grid view. The preference is stored in Redux state via the setIsListView reducer. List view shows documents in a compact table format; grid view shows document cards.
The search feature filters documents by title via the searchDocuments thunk. The search query is sent as a title query parameter to the API. Clearing the search field reloads the default paginated list.
Pinning marks a document as important, causing it to sort to the top of the document list. The pin action patches the document's pinned field on the backend. After pinning, the hook waits 300ms and then refetches the entire document list to reflect the updated sort order.
Users can rename a document inline via the actions dropdown. The handleRenameClick method opens an edit input pre-filled with the current title. On confirmation, handleRename dispatches the updateTitle thunk.
Deletion requires explicit user confirmation through a dialog. Once confirmed, handleDelete dispatches the deleteDocument thunk, which sends a DELETE request to the API. The document is removed from the Redux state on success.
When users run the humanizer, results are automatically saved as documents. There is no manual "create document" action -- documents are created as a side effect of humanization. Each subsequent humanization of the same document creates a new version entry.
Each document contains a version_list array. Every humanization pass adds a new Version object with the input text, output text, word count, and user feedback state. Versions are ordered chronologically.
Within each version, users can save drafts of their manual edits. Drafts are stored in the draft_list array on the version object. Each draft records the edited output_text and a timestamp.
| Date | Author | Change |
|---|---|---|
| 2026-01-30 | Admin | Improved page: corrected TypeScript types (id/user/history are number, not string), added useDocumentActions hook documentation, expanded Redux state and thunk documentation, added feature details, added data model hierarchy diagram |
| 2026-01-30 | Admin | Initial creation |
Prev: Web App - Detector Feature | Next: Web App - Authentication | Up: WalterWrites