On this page

Here's how to create a simple profile page. We'll use GET profile, GET followers, and GET following to display information about a user and their social connections. You can use either the socialfi package (recommended for ease of use) or call the API directly.

## Installing and Setting Up the Socialfi Package (Recommended)

We recommend using the socialfi package as it simplifies the integration process:

```bash
npm install socialfi
```

```ts
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,
});
```

## Getting Profile Information

To get their username and profile information, we can pass their `id` or `username` to the profile endpoint:

### Using the Socialfi Package

```ts
try {
  const profile = await client.profiles.getProfile(
    {
      apiKey: API_KEY,
      profileId: 'ID_OR_USERNAME_HERE'
    }
  );
  console.log('Profile data:', profile);
} catch (error) {
  console.error('Error fetching profile:', error);
}
```

### Using the API Directly

```ts
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/ID_OR_USERNAME_HERE?apiKey=YOUR_API_KEY'
  );
  const profile = await response.json();
  console.log('Profile data:', profile);
} catch (error) {
  console.error('Error fetching profile:', error);
}
```

## Updating Profile Information

Let's imagine our UI has a field for users to update their bio and profile picture. We can add these to their profile on the protocol using the update profile endpoint:

### Using the Socialfi Package

```ts
try {
  const updatedProfile = await client.profiles.updateProfile(
    {
      apiKey: API_KEY,
    },
    {
      profileId: 'USER_ID_HERE',
      customProperties: [
        {
          key: 'bio',
          value: 'Updated bio text here'
        },
        {
          key: 'profileImage',
          value: 'https://example.com/new-profile-image.jpg'
        },
        {
          key: 'location',
          value: 'San Francisco, CA'
        }
      ],
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }
  );
  console.log('Profile updated:', updatedProfile);
} catch (error) {
  console.error('Error updating profile:', error);
}
```

### Using the API Directly

```ts
try {
  const response = await fetch('https://api.usetapestry.dev/v1/profiles/update?apiKey=YOUR_API_KEY', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      profileId: 'USER_ID_HERE',
      customProperties: [
        {
          key: 'bio',
          value: 'Updated bio text here'
        },
        {
          key: 'profileImage',
          value: 'https://example.com/new-profile-image.jpg'
        },
        {
          key: 'location',
          value: 'San Francisco, CA'
        }
      ],
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }),
  });

const updatedProfile = await response.json();
  console.log('Profile updated:', updatedProfile);
} catch (error) {
  console.error('Error updating profile:', error);
}
```

## Getting Complete Profile Information

Now, we will get all of this information back when we call GET profile again:

- username
- bio
- profile image
- following count
- followers count
- custom properties

The profile response will include:

```json
{
  "profile": {
    "id": "user_profile",
    "username": "johndoe",
    "walletAddress": "WALLET_ADDRESS_HERE",
    "blockchain": "SOLANA",
    "customProperties": {
      "bio": "Updated bio text here",
      "profileImage": "https://example.com/new-profile-image.jpg",
      "location": "San Francisco, CA"
    },
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:35:00Z"
  },
  "socialCounts": {
    "followers": 125,
    "following": 89,
    "posts": 42,
    "likes": 367
  }
}
```

## Getting Followers and Following Lists

To enable users to click inside the following & followers counts and get information on each user, we can GET following and GET followers.

### Get Followers

#### Using the Socialfi Package

```ts
try {
  const followers = await client.followers.getFollowers(
    {
      apiKey: API_KEY,
      profileId: 'USER_ID_HERE',
      limit: 20,
      offset: 0
    }
  );
  console.log('Followers:', followers);
} catch (error) {
  console.error('Error fetching followers:', error);
}
```

#### Using the API Directly

```ts
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/followers/USER_ID_HERE?apiKey=YOUR_API_KEY&limit=20&offset=0'
  );
  const followers = await response.json();
  console.log('Followers:', followers);
} catch (error) {
  console.error('Error fetching followers:', error);
}
```

### Get Following

#### Using the Socialfi Package

```ts
try {
  const following = await client.followers.getFollowing(
    {
      apiKey: API_KEY,
      profileId: 'USER_ID_HERE',
      limit: 20,
      offset: 0
    }
  );
  console.log('Following:', following);
} catch (error) {
  console.error('Error fetching following:', error);
}
```

#### Using the API Directly

```ts
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/following/USER_ID_HERE?apiKey=YOUR_API_KEY&limit=20&offset=0'
  );
  const following = await response.json();
  console.log('Following:', following);
} catch (error) {
  console.error('Error fetching following:', error);
}
```

These calls will return data in the following structure:

```json
{
  "users": [
    {
      "profile": {
        "id": "magiceden",
        "username": "magiceden",
        "walletAddress": "2qrWc9p5vatLH3kp4CiVXrdQ4V293d8qzmg4ziez6T4k",
        "customProperties": {
          "bio": "The leading NFT marketplace on Solana",
          "profileImage": "https://example.com/magiceden-avatar.jpg"
        }
      },
      "socialCounts": {
        "followers": 50000,
        "following": 250
      }
    },
    {
      "profile": {
        "id": "idetssx",
        "username": "idetssx",
        "walletAddress": "DPpSMtNnvwNeYhECNv125pfXqYbB2BKbFXaBnpwUc8Js",
        "customProperties": {
          "bio": "Crypto enthusiast and developer",
          "profileImage": "https://example.com/idetssx-avatar.jpg"
        }
      },
      "socialCounts": {
        "followers": 1500,
        "following": 800
      }
    },
    {
      "profile": {
        "id": "pumptothemoon",
        "username": "pumptothemoon",
        "walletAddress": "H2rVxNEiis9zkhxmjAsHrur3apwABxgKMAtj42P4YDDF",
        "customProperties": {
          "bio": "To the moon! 🚀",
          "profileImage": "https://example.com/pump-avatar.jpg"
        }
      },
      "socialCounts": {
        "followers": 5000,
        "following": 2000
      }
    }
  ],
  "pagination": {
    "total": 125,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  }
}
```

## Building the Profile UI

From here, we can use the `id` or `username` to hyperlink to each additional user profile, enhancing discoverability inside our app.

Here's a complete example of how to build a profile page component using the socialfi package:

```ts
async function buildProfilePage(profileId: string) {
  try {
    // Get main profile information
    const profileData = await client.profiles.getProfile({
      apiKey: API_KEY,
      profileId: profileId
    });

// Get followers list
    const followersData = await client.followers.getFollowers({
      apiKey: API_KEY,
      profileId: profileId,
      limit: 10
    });

// Get following list
    const followingData = await client.followers.getFollowing({
      apiKey: API_KEY,
      profileId: profileId,
      limit: 10
    });

// Build your UI with this data
    const profilePageData = {
      profile: profileData.profile,
      socialCounts: profileData.socialCounts,
      followers: followersData.users,
      following: followingData.users
    };

return profilePageData;
  } catch (error) {
    console.error('Error building profile page:', error);
    throw error;
  }
}
```

## Best Practices

When building profile pages:

- **Pagination**: Implement pagination for followers/following lists to handle large numbers
- **Loading States**: Show loading indicators while fetching data
- **Error Handling**: Gracefully handle API errors and network issues
- **Caching**: Consider caching profile data to improve performance
- **Real-time Updates**: Consider implementing real-time updates for social counts
- **Privacy**: Respect user privacy settings and permissions
- **Responsive Design**: Ensure your profile UI works well on all devices
