Skip to main content

Tagging System

To create and manage tags for categorizing bookmarks, use the BookmarkService to handle validation, persistence, and cascading updates across the system.

Creating a Tag

Create a new tag by passing a dictionary of attributes to BookmarkService.create_tag. This method validates the tag name against length constraints and reserved words before persisting it.

from app.services.bookmark_service import BookmarkService
from app.models.tag import TagColor

service = BookmarkService()

tag_data = {
"name": "Research",
"color": "blue", # Corresponds to TagColor.BLUE
"description": "Academic and work-related research"
}

tag, error = service.create_tag(tag_data)

if error:
print(f"Failed to create tag: {error}")
else:
print(f"Created tag: {tag.name} (ID: {tag.id})")

Tag Attributes and Colors

The Tag class (found in app/models/tag.py) includes several key attributes:

  • name: The display name. Must be unique and non-reserved.
  • color: A TagColor enum value. Defaults to TagColor.GRAY.
  • usage_count: An integer tracking how many bookmarks currently use this tag.
  • id: An 8-character unique identifier generated automatically.

Available colors are defined in the TagColor enum:

class TagColor(Enum):
RED = "red"
BLUE = "blue"
GREEN = "green"
YELLOW = "yellow"
PURPLE = "purple"
GRAY = "gray"

Updating and Renaming Tags

Use BookmarkService.update_tag to modify an existing tag. This method ensures that name changes still adhere to validation rules.

update_data = {
"name": "Deep Research",
"color": "purple"
}

updated_tag, error = service.update_tag(tag.id, update_data)

if not error:
print(f"Updated tag name to: {updated_tag.name}")

Listing and Sorting Tags

The BookmarkService.list_tags method returns all tags. Because the Tag class implements the __lt__ dunder method, you can easily sort them alphabetically by name.

tags = service.list_tags()

# Sort tags alphabetically (case-insensitive)
for t in sorted(tags):
print(f"{t.name} - {t.usage_count} bookmarks")

Deleting Tags (Cascading)

When you delete a tag using BookmarkService.delete_tag, the service automatically removes that tag from every bookmark that uses it before deleting the tag itself.

# This removes the tag from all associated bookmarks and then deletes it
success = service.delete_tag(tag.id)

if success:
print("Tag deleted and removed from all bookmarks.")

Tracking Tag Usage

While the BookmarkService manages high-level operations, the Tag model provides methods to manually track how many bookmarks are using a specific tag.

# Increment usage when a bookmark is tagged
new_count = tag.increment_usage()

# Decrement usage when a tag is removed (clamped at 0)
new_count = tag.decrement_usage()

Troubleshooting and Constraints

When managing tags, keep the following constraints from app/models/_validators.py in mind:

  • Reserved Names: You cannot name a tag all, untagged, archived, or trash. These are reserved for system filters.
  • Length Limits: Tag names must be between 1 and 50 characters long.
  • Unique IDs: Tags use a truncated UUID (8 characters). If you are manually constructing tags from dictionaries, ensure the id is handled correctly or let the Tag constructor generate one.
  • Color Validation: When updating via the service, the color string must match one of the values in the TagColor enum, or a ValueError will be raised during the TagColor(data["color"]) conversion.