Last Updated: 3/17/2026
Data Models and Database Schema
LinkAce is built on Laravel and uses Eloquent ORM for database interactions. This document describes the core data models and their relationships.
Core Models Overview
LinkAce has five primary models:
- Link - A bookmarked URL with metadata
- LinkList - A collection/category for organizing links
- Tag - A label for categorizing links
- Note - A text note attached to a link
- User - A user account
Link Model
The Link model represents a bookmarked URL and is the central entity in LinkAce.
Fields
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
user_id | integer | Foreign key to User |
url | string | The bookmarked URL |
title | string | Title of the link |
description | string (nullable) | Description text (supports Markdown) |
icon | string (nullable) | Icon identifier |
visibility | integer | Visibility level (1=private, 2=internal, 3=public) |
status | integer | Health check status (1=OK, 2=moved, 3=broken) |
check_disabled | boolean | Whether automated checks are disabled |
last_checked_at | datetime (nullable) | Last health check timestamp |
thumbnail | string (nullable) | Thumbnail URL |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
deleted_at | datetime (nullable) | Soft delete timestamp |
Relationships
- belongsTo:
User- The link owner - belongsToMany:
LinkList- Lists containing this link (vialink_listspivot table) - belongsToMany:
Tag- Tags applied to this link (vialink_tagspivot table) - hasMany:
Note- Notes attached to this link
Status Constants
const STATUS_OK = 1; // Link is accessible
const STATUS_MOVED = 2; // Link redirected
const STATUS_BROKEN = 3; // Link is brokenKey Methods
shortUrl(): Returns URL without http(s):// prefixshortTitle($maxLength): Returns truncated titledomainOfURL(): Extracts domain from URLgetFormattedDescriptionAttribute(): Returns Markdown-formatted descriptionsearchDuplicateUrls(): Finds potential duplicate linksinitiateInternetArchiveBackup(): Queues Wayback Machine backup
Scopes
byUser($user_id): Filter links by userprivateOnly(): Only private linksinternalOnly(): Only internal linkspublicOnly(): Only public links
LinkList Model
The LinkList model represents a collection or category of links.
Fields
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
user_id | integer | Foreign key to User |
name | string | List name |
description | string (nullable) | Description (supports Markdown) |
visibility | integer | Visibility level (1=private, 2=internal, 3=public) |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
deleted_at | datetime (nullable) | Soft delete timestamp |
Relationships
- belongsTo:
User- The list owner - belongsToMany:
Link- Links in this list (vialink_listspivot table)
Key Methods
getFormattedDescriptionAttribute(): Returns Markdown-formatted description
Ordering
Lists are automatically ordered by name (via OrderNameScope global scope).
Tag Model
The Tag model represents a label for categorizing links.
Fields
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
user_id | integer | Foreign key to User |
name | string | Tag name |
visibility | integer | Visibility level (1=private, 2=internal, 3=public) |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
deleted_at | datetime (nullable) | Soft delete timestamp |
Relationships
- belongsTo:
User- The tag owner - belongsToMany:
Link- Links with this tag (vialink_tagspivot table)
Ordering
Tags are automatically ordered by name (via OrderNameScope global scope).
Note Model
The Note model represents a text note attached to a link.
Fields
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
link_id | integer | Foreign key to Link |
user_id | integer | Foreign key to User |
note | text | Note content (supports Markdown) |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
deleted_at | datetime (nullable) | Soft delete timestamp |
Relationships
- belongsTo:
Link- The associated link - belongsTo:
User- The note author
User Model
The User model represents a user account in LinkAce.
Fields
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
name | string | User’s display name |
email | string | Email address (unique) |
password | string | Hashed password |
email_verified_at | datetime (nullable) | Email verification timestamp |
is_admin | boolean | Admin flag |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
deleted_at | datetime (nullable) | Soft delete timestamp |
Relationships
- hasMany:
Link- Links owned by this user - hasMany:
LinkList- Lists owned by this user - hasMany:
Tag- Tags owned by this user - hasMany:
Note- Notes created by this user
Pivot Tables
link_lists
Links the links and lists tables in a many-to-many relationship.
| Field | Type | Description |
|---|---|---|
link_id | integer | Foreign key to links |
list_id | integer | Foreign key to lists |
link_tags
Links the links and tags tables in a many-to-many relationship.
| Field | Type | Description |
|---|---|---|
link_id | integer | Foreign key to links |
tag_id | integer | Foreign key to tags |
Visibility System
All primary models (Link, LinkList, Tag) support a three-level visibility system:
| Level | Constant | Description |
|---|---|---|
| 1 | VISIBILITY_PRIVATE | Only visible to the owner |
| 2 | VISIBILITY_INTERNAL | Visible to all authenticated users |
| 3 | VISIBILITY_PUBLIC | Visible to everyone, including guests |
The visibility system is implemented via the ScopesVisibility trait, which provides query scopes for filtering resources by visibility level.
Soft Deletes
All core models use Laravel’s soft delete feature. When a record is deleted, it’s marked with a deleted_at timestamp rather than being permanently removed from the database. This allows for:
- Trash/restore functionality
- Audit trail preservation
- Relationship integrity maintenance
Audit Trail
LinkAce uses the owen-it/laravel-auditing package to track changes to models. All core models implement the Auditable interface and maintain a complete audit log of:
- Create, update, and delete operations
- Field-level changes with old and new values
- Relationship modifications
- User attribution
Custom audit modifiers format certain fields for better readability:
VisibilityModifier: Formats visibility levelsBooleanModifier: Formats boolean valuesLinkStatusModifier: Formats link status codesTagRelationModifier/ListRelationModifier: Formats relationship changes
Repository Pattern
LinkAce uses the Repository pattern for complex business logic. Key repositories include:
- LinkRepository: Handles link creation, updates, and deletion with associated relationships
- Creates/updates lists and tags inline
- Manages Internet Archive backups
- Handles duplicate detection
Model Traits
ScopesForUser
Provides the byUser() query scope for filtering resources by user ownership.
ScopesVisibility
Provides query scopes for visibility filtering:
privateOnly()internalOnly()publicOnly()visibleForUser($userId, $privateSystemAccess)
ProvidesTaxonomyOutput
Used by Link model to provide formatted output for taxonomy relationships (lists and tags).
Database Migrations
LinkAce uses Laravel migrations for schema management. All migrations are version-controlled and can be found in the database/migrations directory. Key migrations include:
- User and authentication tables
- Core model tables (links, lists, tags, notes)
- Pivot tables for many-to-many relationships
- Audit and session tables
- OAuth/SSO tables
For collation settings and database-specific configuration, see Adjusting the Database Collation.