Adding Likes to Content or Profiles | Tapestry Documentation

Likes are a fundamental engagement mechanism in social applications. The Tapestry Likes API allows users to express appreciation for content and interact with posts. You can use either the socialfi package (recommended for simpler integration) or call the API directly.

Installing and Setting Up the Socialfi Package (Recommended)

We recommend using the socialfi package as it provides a cleaner, more maintainable approach:

npm install socialfi
import { SocialFi } from 'socialfi';

const API_URL = 'https://api.usetapestry.dev/v1/'; // tapestry prod URL
// const API_URL = 'https://api.dev.usetapestry.dev/v1/'; // tapestry dev URL

const API_KEY = process.env.TAPESTRY_API_KEY; // Get your API key from https://app.usetapestry.dev/

const client = new SocialFi({
  baseURL: API_URL,
  apiKey: API_KEY,
});

Creating a Like

To allow users to like a post or content, use the like creation endpoint:

Using the Socialfi Package

try {
  const newLike = await client.likes.createLike(
    {
      apiKey: API_KEY,
    },
    {
      profileId: 'user123', // The ID of the profile creating the like
      contentId: 'post456', // The ID of the content being liked
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }
  );
  console.log('Like created:', newLike);
} catch (error) {
  console.error('Error creating like:', error);
}

Using the API Directly

try {
  const response = await fetch('https://api.usetapestry.dev/v1/likes?apiKey=YOUR_API_KEY', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      profileId: 'user123',
      contentId: 'post456',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }),
  });

const newLike = await response.json();
  console.log('Like created:', newLike);
} catch (error) {
  console.error('Error creating like:', error);
}

Request Parameters

Field Type Description
profileId string The ID of the profile creating the like.
contentId string The ID of the content being liked.
blockchain string The blockchain to use (default: SOLANA)
execution string Execution method (default: FAST_UNCONFIRMED)

Response Example

{
  "like": {
    "id": "like-1234567890",
    "profileId": "user123",
    "contentId": "post456",
    "blockchain": "SOLANA",
    "createdAt": "2024-01-15T10:30:00Z"
  },
  "user": {
    "id": "user123",
    "username": "johndoe",
    "profileImage": "https://example.com/avatar.jpg"
  }
}

Removing a Like (Unlike)

To allow users to unlike content they previously liked:

Using the Socialfi Package

try {
  const result = await client.likes.deleteLike(
    {
      apiKey: API_KEY,
    },
    {
      profileId: 'user123',
      contentId: 'post456',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }
  );
  console.log('Like removed:', result);
} catch (error) {
  console.error('Error removing like:', error);
}

Using the API Directly

try {
  const response = await fetch('https://api.usetapestry.dev/v1/likes?apiKey=YOUR_API_KEY', {
    method: 'DELETE',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      profileId: 'user123',
      contentId: 'post456',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }),
  });

const result = await response.json();
  console.log('Like removed:', result);
} catch (error) {
  console.error('Error removing like:', error);
}

Response Example

{
  "success": true,
  "message": "Like removed successfully"
}

Getting Likes for Content

To retrieve all likes for a specific piece of content:

Using the Socialfi Package

try {
  const likes = await client.likes.getLikesByContent(
    {
      apiKey: API_KEY,
      contentId: 'post456',
      limit: 20,
      offset: 0
    }
  );
  console.log('Likes for content:', likes);
} catch (error) {
  console.error('Error fetching likes:', error);
}

Using the API Directly

try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/likes/content/post456?apiKey=YOUR_API_KEY&limit=20&offset=0'
  );
  const likes = await response.json();
  console.log('Likes for content:', likes);
} catch (error) {
  console.error('Error fetching likes:', error);
}

Query Parameters

Parameter Type Description
contentId string The ID of the content to get likes for.
limit number Maximum number of likes to return.
offset number Number of likes to skip.

Response Example

{
  "likes": [
    {
      "like": {
        "id": "like-1234567890",
        "createdAt": "2024-01-15T10:30:00Z"
      },
      "user": {
        "id": "user123",
        "username": "johndoe",
        "profileImage": "https://example.com/avatar1.jpg"
      }
    },
    {
      "like": {
        "id": "like-0987654321",
        "createdAt": "2024-01-15T11:00:00Z"
      },
      "user": {
        "id": "user789",
        "username": "janedoe",
        "profileImage": "https://example.com/avatar2.jpg"
      }
    }
  ],
  "pagination": {
    "total": 45,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  },
  "likeCount": 45
}

Getting Likes by User

To retrieve all content that a specific user has liked:

Using the Socialfi Package

try {
  const userLikes = await client.likes.getLikesByProfile(
    {
      apiKey: API_KEY,
      profileId: 'user123',
      limit: 10,
      offset: 0
    }
  );
  console.log('Content liked by user:', userLikes);
} catch (error) {
  console.error('Error fetching user likes:', error);
}

Using the API Directly

try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/likes/profile/user123?apiKey=YOUR_API_KEY&limit=10&offset=0'
  );
  const userLikes = await response.json();
  console.log('Content liked by user:', userLikes);
} catch (error) {
  console.error('Error fetching user likes:', error);
}

Response Example

{
  "likes": [
    {
      "like": {
        "id": "like-1234567890",
        "createdAt": "2024-01-15T10:30:00Z"
      },
      "content": {
        "id": "post456",
        "content": "Amazing post about blockchain technology!",
        "author": {
          "id": "user789",
          "username": "contentcreator"
        }
      }
    }
  ],
  "pagination": {
    "total": 25,
    "limit": 10,
    "offset": 0,
    "hasMore": true
  }
}

Checking if User Liked Content

To check if a specific user has liked a specific piece of content:

Using the Socialfi Package

try {
  const hasLiked = await client.likes.checkUserLikedContent(
    {
      apiKey: API_KEY,
      profileId: 'user123',
      contentId: 'post456'
    }
  );
  console.log('User has liked this content:', hasLiked.hasLiked);
} catch (error) {
  console.error('Error checking like status:', error);
}

Using the API Directly

try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/likes/check?apiKey=YOUR_API_KEY&profileId=user123&contentId=post456'
  );
  const hasLiked = await response.json();
  console.log('User has liked this content:', hasLiked.hasLiked);
} catch (error) {
  console.error('Error checking like status:', error);
}

Response Example

{
  "hasLiked": true,
  "likeId": "like-1234567890",
  "likedAt": "2024-01-15T10:30:00Z"
}

Like Counts

To get just the like count for content without fetching all individual likes:

Using the Socialfi Package

try {
  const likeCount = await client.likes.getLikeCount(
    {
      apiKey: API_KEY,
      contentId: 'post456'
    }
  );
  console.log('Like count:', likeCount.count);
} catch (error) {
  console.error('Error fetching like count:', error);
}

Using the API Directly

try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/likes/count/post456?apiKey=YOUR_API_KEY'
  );
  const likeCount = await response.json();
  console.log('Like count:', likeCount.count);
} catch (error) {
  console.error('Error fetching like count:', error);
}

Response Example

{
  "contentId": "post456",
  "count": 45,
  "lastUpdated": "2024-01-15T11:30:00Z"
}

Building Like Functionality

Here's a complete example of how to implement like/unlike functionality in your app using the socialfi package:

interface LikeButtonProps {
  contentId: string;
  currentUserId: string;
}

class LikeButton {
  private contentId: string;
  private currentUserId: string;
  private isLiked: boolean = false;
  private likeCount: number = 0;

constructor(props: LikeButtonProps) {
    this.contentId = props.contentId;
    this.currentUserId = props.currentUserId;
    this.initializeLikeStatus();
  }

async initializeLikeStatus() {
    try {
      // Check if user has liked this content
      const likeStatus = await client.likes.checkUserLikedContent({
        apiKey: API_KEY,
        profileId: this.currentUserId,
        contentId: this.contentId
      });

// Get current like count
      const likeCountData = await client.likes.getLikeCount({
        apiKey: API_KEY,
        contentId: this.contentId
      });

this.isLiked = likeStatus.hasLiked;
      this.likeCount = likeCountData.count;

this.updateUI();
    } catch (error) {
      console.error('Error initializing like status:', error);
    }
  }

async toggleLike() {
    try {
      if (this.isLiked) {
        // Unlike the content
        await client.likes.deleteLike(
          {
            apiKey: API_KEY,
          },
          {
            profileId: this.currentUserId,
            contentId: this.contentId,
            blockchain: 'SOLANA'
          }
        );
        this.isLiked = false;
        this.likeCount--;
      } else {
        // Like the content
        await client.likes.createLike(
          {
            apiKey: API_KEY,
          },
          {
            profileId: this.currentUserId,
            contentId: this.contentId,
            blockchain: 'SOLANA'
          }
        );
        this.isLiked = true;
        this.likeCount++;
      }

this.updateUI();
    } catch (error) {
      console.error('Error toggling like:', error);
      // Revert optimistic update on error
      this.initializeLikeStatus();
    }
  }

private updateUI() {
    // Update your UI elements here
    console.log(`Like button - Liked: ${this.isLiked}, Count: ${this.likeCount}`);
  }
}

Real-time Like Updates

For real-time like updates, you can implement polling or use WebSocket connections:

// Polling example
async function pollLikeUpdates(contentId: string, intervalMs: number = 5000) {
  setInterval(async () => {
    try {
      const likeCount = await client.likes.getLikeCount({
        apiKey: API_KEY,
        contentId: contentId
      });

// Update your UI with the new count
      updateLikeCountInUI(contentId, likeCount.count);
    } catch (error) {
      console.error('Error polling like updates:', error);
    }
  }, intervalMs);
}

Best Practices

When implementing likes functionality: