Homepage Links Backend Plugin
The Homepage Links Backend provides persistence for user homepage preferences, onboarding links, and team documentation links.
Overview
| Property | Value |
|---|---|
| Package | @internal/plugin-homepage-links-backend |
| Type | Backend |
| Plugin ID | homepage-links |
| Database | PostgreSQL via Knex |
Architecture
API Endpoints
Links
| Method | Endpoint | Description |
|---|---|---|
| GET | /links | Get user's links |
| GET | /links/by-group/:groupRef | Get links for group |
| POST | /links | Create new link |
| DELETE | /links/:id | Delete entire link |
| DELETE | /links/:id/groups/:groupRef | Remove link from group |
| GET | /autocomplete | Search existing links |
Preferences
| Method | Endpoint | Description |
|---|---|---|
| GET | /preferences | Get user preferences |
| PUT | /preferences | Update preferences |
User Info
| Method | Endpoint | Description |
|---|---|---|
| GET | /user-groups | Get current user's groups |
Database Schema
homepage_links
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| title | VARCHAR | Link title |
| url | VARCHAR | Link URL |
| description | TEXT | Optional description |
| type | VARCHAR | 'onboarding' or 'team' |
| icon | VARCHAR | Icon identifier |
| group_refs | JSONB | Array of group refs |
| created_by | VARCHAR | Creator user reference |
| created_at | TIMESTAMP | Creation time |
| updated_at | TIMESTAMP | Last update time |
user_preferences
| Column | Type | Description |
|---|---|---|
| user_ref | VARCHAR | Primary key (user ref) |
| collapsed_sections | JSONB | Array of collapsed IDs |
| hidden_items | JSONB | Array of hidden item IDs |
| group_order | JSONB | Custom group ordering |
| updated_at | TIMESTAMP | Last update time |
Link Types
Onboarding Links
Links shown in the onboarding section for new team members:
interface OnboardingLink {
id: string;
title: string;
url: string;
description: string;
type: "onboarding";
icon: "book" | "code" | "settings" | "help";
groupRefs: string[];
}
Team Links
Links for team documentation and resources:
interface TeamLink {
id: string;
title: string;
url: string;
description: string;
type: "team";
icon: "docs" | "wiki" | "repo" | "dashboard";
groupRefs: string[];
}
Request/Response Schemas
Create Link
// POST /links
interface CreateLinkRequest {
title: string;
url: string;
description?: string;
type: "onboarding" | "team";
icon?: string;
groupRefs: string[];
}
// Zod schema
const createLinkSchema = z.object({
title: z.string().min(1).max(255),
url: z.string().url(),
description: z.string().max(1000).optional(),
type: z.enum(["onboarding", "team"]),
icon: z.string().optional(),
groupRefs: z.array(z.string()).min(1),
});
User Preferences
// PUT /preferences
interface UpdatePreferencesRequest {
collapsedSections?: string[];
hiddenItems?: string[];
groupOrder?: string[];
}
// Zod schema
const updatePreferencesSchema = z.object({
collapsedSections: z.array(z.string()).optional(),
hiddenItems: z.array(z.string()).optional(),
groupOrder: z.array(z.string()).optional(),
});
LinksStore Service
interface LinksStore {
// Link operations
getLinks(groupRefs: string[]): Promise<Link[]>;
getLinksByGroup(groupRef: string): Promise<Link[]>;
createLink(input: CreateLinkInput, createdBy: string): Promise<Link>;
deleteLink(id: string): Promise<void>;
removeLinkFromGroup(id: string, groupRef: string): Promise<void>;
autocomplete(query: string): Promise<Link[]>;
// Preference operations
getPreferences(userRef: string): Promise<UserPreferences>;
updatePreferences(
userRef: string,
prefs: Partial<UserPreferences>,
): Promise<UserPreferences>;
// User info
getUserGroups(claims: JWTClaims): string[];
}
Group-Based Access
Links are scoped to groups:
URL Normalization
URLs are normalized before storage:
class UrlNormalizer {
normalize(url: string): string {
// Add protocol if missing
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = "https://" + url;
}
// Remove trailing slash
url = url.replace(/\/$/, "");
// Lowercase domain
const parsed = new URL(url);
parsed.hostname = parsed.hostname.toLowerCase();
return parsed.toString();
}
}
Usage Examples
Create Onboarding Link
curl -X POST http://localhost:7007/api/homepage-links/links \
-H "Content-Type: application/json" \
-d '{
"title": "Getting Started Guide",
"url": "https://docs.example.com/onboarding",
"description": "New team member onboarding documentation",
"type": "onboarding",
"icon": "book",
"groupRefs": ["group:default/platform-team"]
}'
Get User's Links
curl http://localhost:7007/api/homepage-links/links
Update Preferences
curl -X PUT http://localhost:7007/api/homepage-links/preferences \
-H "Content-Type: application/json" \
-d '{
"collapsedSections": ["onboarding"],
"groupOrder": ["platform-team", "devops"]
}'
Related Documentation
- Homepage Links Frontend - Frontend plugin
- Homepage Repos Backend - Repository management
- Plugins Overview