ArcHive automatically detects and categorizes your saved links by their source platform, making it easy to find all content from specific websites or services.
When you save a link, ArcHive automatically identifies the platform:
export const extractPlatformFromUrl = ( url : string ) : string => {
try {
const urlObj = new URL ( url );
const hostname = urlObj . hostname . toLowerCase ();
const domain = hostname . replace ( / ^ www \. / , "" );
if ( domain . includes ( "github.com" )) return PLATFORMS . GITHUB ;
if ( domain . includes ( "youtube.com" ) || domain . includes ( "youtu.be" ))
return PLATFORMS . YOUTUBE ;
if ( domain . includes ( "twitter.com" ) || domain . includes ( "x.com" ))
return PLATFORMS . TWITTER ;
if ( domain . includes ( "instagram.com" )) return PLATFORMS . INSTAGRAM ;
if ( domain . includes ( "linkedin.com" )) return PLATFORMS . LINKEDIN ;
// ... more platforms
// For unknown platforms, use the domain name
const parts = domain . split ( "." );
if ( parts . length >= 2 ) {
return parts . slice ( - 2 ). join ( "." );
}
return domain || PLATFORMS . OTHER ;
} catch ( error ) {
return PLATFORMS . OTHER ;
}
};
Source: backend/src/constants/platforms.ts:26-67
ArcHive has built-in support for major platforms:
GitHub Code repositories and projects
YouTube Videos and channels
Twitter/X Tweets and threads
LinkedIn Professional content
Reddit Discussions and posts
Medium Articles and stories
Stack Overflow Q&A and solutions
Pinterest Images and boards
Telegram Messages and channels
For platforms not in the predefined list, ArcHive automatically uses the domain name (e.g., “example.com”) as the platform identifier.
Platform identifiers are defined as constants:
export const PLATFORMS = {
GITHUB: "github" ,
YOUTUBE: "youtube" ,
TWITTER: "twitter" ,
INSTAGRAM: "instagram" ,
LINKEDIN: "linkedin" ,
REDDIT: "reddit" ,
MEDIUM: "medium" ,
STACKOVERFLOW: "stackoverflow" ,
FACEBOOK: "facebook" ,
TIKTOK: "tiktok" ,
TWITCH: "twitch" ,
PINTEREST: "pinterest" ,
VIMEO: "vimeo" ,
DISCORD: "discord" ,
TELEGRAM: "telegram" ,
OTHER: "other" ,
} as const ;
Source: backend/src/constants/platforms.ts:1-18
Get a breakdown of your content by platform:
contentRoutes . get ( "/platforms" , async ( c ) => {
const userId = c . get ( "user" )?. _id ;
const platforms = await getPlatforms ( userId );
return c . json (
{
message: "Platforms retrieved successfully" ,
platforms: platforms ,
},
200 ,
);
});
Source: backend/src/routes/content.ts:142-161
The platform statistics are calculated using MongoDB aggregation:
async function getPlatforms ( userId : string ) {
const userObjectId = new mongoose . Types . ObjectId ( userId );
const platformStats = await ContentItem . aggregate ([
{
$match: {
userId: userObjectId ,
platform: { $ne: null },
},
},
{
$group: {
_id: "$platform" ,
count: { $sum: 1 },
},
},
{
$sort: { count: - 1 },
},
{
$project: {
_id: 0 ,
platform: "$_id" ,
count: 1 ,
},
},
]);
return platformStats ;
}
Source: backend/src/services/content.service.ts:296-330
Response Format:
{
"message" : "Platforms retrieved successfully" ,
"platforms" : [
{ "platform" : "github" , "count" : 42 },
{ "platform" : "youtube" , "count" : 28 },
{ "platform" : "medium" , "count" : 15 }
]
}
The mobile app includes a dedicated Browse screen for platform-based navigation:
Browse Screen UI Flow
Access Browse Tab
Navigate to the Browse tab in the bottom navigation
View Platform Statistics
See all platforms with saved content and item counts: const { data : platforms , isLoading , error , refetch } = useQuery ({
queryKey: [ "platforms" ],
queryFn: getPlatforms ,
});
Source: archive/app/(tabs)/browse.tsx:18-26
Select a Platform
Tap any platform card to view all content from that source
Browse Platform Content
The platform-specific view shows all your saved items from that platform, with the same search and filtering capabilities
Each platform is displayed as an interactive card:
< FlatList
data = { platforms }
keyExtractor = {(item) => item. platform }
renderItem = {({ item }) => (
<PlatformCard platform = {item. platform } count = {item. count } />
)}
contentContainerStyle = {styles. list }
refreshControl = {
< RefreshControl
refreshing = { isRefetching }
onRefresh = { refetch }
tintColor = {Colors.light. tint }
/>
}
/>
Source: archive/app/(tabs)/browse.tsx:60-74
The Browse screen supports pull-to-refresh to update platform statistics in real-time.
You can filter your content by platform using the API:
const searchContentQuerySchema = z . object ({
q: z . string (). trim (). min ( 1 , "Search query cannot be empty" ). optional (),
type: z . nativeEnum ( ContentType ). optional (),
tag: z . string (). trim (). min ( 1 , "Tag cannot be empty" ). optional (),
platform: z . string (). trim (). min ( 1 , "Platform cannot be empty" ). optional (),
limit: z . coerce . number (). int (). min ( 1 ). max ( 100 ). default ( 20 ). optional (),
page: z . coerce . number (). int (). min ( 1 ). default ( 1 ). optional (),
}). partial ();
Source: backend/src/validation/content.validation.ts:101-110
Example API Request
GET /api/content?platform=github & limit = 20 & page = 1
This returns all GitHub repositories you’ve saved.
if ( platform ) {
findCriteria . platform = platform ;
}
const contents = await ContentItem . find ( findCriteria )
. sort ({ createdAt: - 1 })
. skip ( skip )
. limit ( limit );
Source: backend/src/services/content.service.ts:158-170
Each platform parser extracts platform-specific metadata:
In the mobile app, platform badges appear on content cards with platform-specific icons and colors for quick visual identification.
UI Implementation:
Each platform has a dedicated icon (from FontAwesome5)
Platform name appears as a badge
Tapping a platform badge navigates to the platform-specific browse view
Database Indexing
For optimal query performance, ArcHive maintains a compound index on user and platform:
ContentItemSchema . index ({ userId: 1 , platform: 1 });
Source: backend/src/db/models/ContentItem.ts:100
This index enables fast queries like:
“Show all my YouTube videos”
“Find my GitHub repositories”
“List all Medium articles I’ve saved”
Empty State Handling
When no content exists for a platform:
if ( ! platforms || platforms . length === 0 ) {
return (
< View style = {styles. container } >
< EmptyState type = "default" />
</ View >
);
}
Source: archive/app/(tabs)/browse.tsx:44-50
Next Steps
Search Learn about full-text search capabilities
Intelligent Parsing See how metadata is extracted