ArcHive provides powerful organization features to help you keep your digital knowledge base structured and easily accessible.
Content Structure
Each content item in ArcHive follows a well-defined schema:
export interface IContentItem extends Document {
userId : Types . ObjectId ;
type : ContentType ; // "text" | "link" | "code"
title ?: string ; // Up to 200 characters
description ?: string ; // Up to 1,000 characters
content : string ; // Up to 100,000 characters
url ?: string ; // Valid URL for links
tags : string []; // Array of tag strings
previewImageUrl ?: string ; // Cloudinary URL for screenshots
platform ?: string | null ; // Platform identifier
createdAt : Date ;
updatedAt : Date ;
}
Source: backend/src/db/models/ContentItem.ts:9-21
Tagging System
Tags are a powerful way to categorize and find your content:
Automatic Tag Normalization
All tags are automatically normalized for consistency:
tags : {
type : [ String ],
default : [],
set : ( v : string []) =>
v
. map (( tag ) => tag . trim (). toLowerCase ())
. filter (( tag ) => tag . length > 0 ),
}
Source: backend/src/db/models/ContentItem.ts:56-63
Tags are automatically converted to lowercase and trimmed, ensuring “JavaScript”, “javascript”, and ” JavaScript ” are all treated as the same tag.
Manual Tagging
You can add custom tags when creating or editing content:
During Content Creation
Add tags when initially saving content: {
"type" : "link" ,
"url" : "https://example.com" ,
"tags" : [ "tutorial" , "javascript" , "web-dev" ]
}
Edit Existing Content
Update tags on existing items via the PUT endpoint: await updateContent ( userId , contentId , {
tags: [ "updated" , "tags" , "list" ]
});
Automatic Tag Suggestions
For links, ArcHive automatically generates tag suggestions by analyzing the page content using NLP. These suggestions are processed asynchronously and appear after the initial save.
Content Types
Organize content by type for focused browsing:
Type Filtering in the Mobile App
The mobile app provides visual filters for content types:
const contentTypes = [ "All" , "Link" , "Text" , "Code" ];
// Filter implementation
findCriteria . type = type ;
UI Flow:
Tap the search icon in the header
Filter buttons appear below the search bar
Select a type to filter (All, Link, Text, Code)
Content list updates in real-time
Source: archive/app/(tabs)/index.tsx:40-160
Links Web URLs with metadata and screenshots
Text Notes, thoughts, and written content
Code Code snippets and examples
Updating Content
You can update any aspect of your saved content:
contentRoutes . put (
"/:id" ,
apiRateLimiter ,
validate ( "json" , updateContentSchema ),
async ( c ) => {
const userId = c . get ( "user" )?. _id ;
const contentId = c . req . param ( "id" );
const updates = c . req . valid ( "json" ) as UpdateContentInput ;
const updatedContent = await updateContent ( userId , contentId , updates );
return c . json ({
message: "Content item updated successfully!" ,
content: updatedContent . toObject (),
});
},
);
Source: backend/src/routes/content.ts:186-211
Update Validation
Content type cannot be changed after creation. Attempting to change a link to text or vice versa will result in a validation error.
if ( existing && existing . type !== updates . type ) {
throw new ValidationError (
`Content type cannot be changed. Expected ${ existing . type } , got ${ updates . type } .` ,
);
}
Source: backend/src/services/content.service.ts:216-220
Updatable Fields
View all updatable fields
title : Change the title (max 200 characters)
description : Update the description (max 1,000 characters)
tags : Modify the tag list
content : Edit text or code content (max 100,000 characters)
url : Update the URL (links only)
previewImageUrl : Change the preview image
platform : Modify platform categorization
Deleting Content
Remove content you no longer need:
contentRoutes . delete ( "/:id" , apiRateLimiter , async ( c ) => {
const userId = c . get ( "user" )?. _id ;
const contentId = c . req . param ( "id" );
await deleteContent ( userId , contentId );
return c . json (
{
message: "Content item deleted successfully!" ,
},
200 ,
);
});
Source: backend/src/routes/content.ts:214-232
Deletion only works for content you own. Attempting to delete another user’s content will result in a 404 error.
Full-Text Search Index
ArcHive maintains a full-text search index for fast retrieval:
ContentItemSchema . index (
{
title: "text" ,
description: "text" ,
content: "text" ,
url: "text" ,
tags: "text" ,
},
{
name: "ContentItemTextIndex" ,
weights: {
title: 10 ,
tags: 5 ,
description: 3 ,
content: 1 ,
url: 1 ,
},
},
);
Source: backend/src/db/models/ContentItem.ts:80-98
The search index is weighted, meaning matches in titles (weight: 10) are ranked higher than matches in content (weight: 1).
For efficient platform-based browsing, ArcHive maintains a compound index:
ContentItemSchema . index ({ userId: 1 , platform: 1 });
Source: backend/src/db/models/ContentItem.ts:100
This enables fast queries like “Show me all my GitHub repositories” or “Find my YouTube videos.”
All content queries support pagination to handle large collections:
const skip = ( page - 1 ) * limit ;
let contentsQuery = ContentItem . find ( findCriteria )
. sort ({ createdAt: - 1 })
. skip ( skip )
. limit ( limit );
Source: backend/src/services/content.service.ts:165-170
Default Pagination:
Default page size: 20 items
Maximum page size: 100 items
Sort order: Most recent first (createdAt descending)
Mobile App Organization Features
The mobile app uses TanStack Query for optimized infinite scrolling:
const {
data ,
fetchNextPage ,
hasNextPage ,
isFetchingNextPage ,
refetch ,
isRefetching ,
} = useInfiniteQuery ({
queryKey: [ "contents" , debouncedSearchQuery , selectedContentType ],
queryFn : async ({ pageParam = 1 }) => {
const response = await getContent (
debouncedSearchQuery ,
pageParam ,
10 ,
selectedContentType === "All" ? undefined : selectedContentType . toLowerCase (),
);
return response ;
},
getNextPageParam : ( lastPage ) => {
if ( lastPage . meta . page < lastPage . meta . totalPages ) {
return lastPage . meta . page + 1 ;
}
return undefined ;
},
initialPageParam: 1 ,
});
Source: archive/app/(tabs)/index.tsx:52-82
Pull to Refresh
All content lists support pull-to-refresh for manual updates:
< ContentList
contentItems = {content || []}
onRefresh={refetch}
refreshing={isRefetching}
// ...
/>
Next Steps
Search Learn about powerful search capabilities
Platform Categorization Browse content by platform