# Extend news feed dapp · Chromia for EVM developers · Learn Chromia

> Once the core is ready, you can let users follow each other and read a feed of posts from the accounts they follow. Both Solidity and Rell handle this…

Source: https://chromia.com/learn/chromia-for-evm-developers/news-feed-follower/

Chromia for EVM developersLesson 7 of 8

1. [01Chromia for EVM developers](https://chromia.com/learn/chromia-for-evm-developers/introduction/)
2. [02Explore assets and transfers](https://chromia.com/learn/chromia-for-evm-developers/asset-transfer/)
3. [03Chromia dapp overview](https://chromia.com/learn/chromia-for-evm-developers/chromia-stack/)
4. [04Authentication](https://chromia.com/learn/chromia-for-evm-developers/compare-authentication/)
5. [05Core concepts](https://chromia.com/learn/chromia-for-evm-developers/concepts/)
6. [06Create a news feed dapp](https://chromia.com/learn/chromia-for-evm-developers/news-feed/)
7. [07Extend news feed dapp](https://chromia.com/learn/chromia-for-evm-developers/news-feed-follower/)
8. [08Summary](https://chromia.com/learn/chromia-for-evm-developers/summary/)

[Learn](https://chromia.com/learn/)[Chromia for EVM developers](https://chromia.com/learn/chromia-for-evm-developers/)

07 / 08

# Extend news feed dapp

Once the core is ready, you can let users follow each other and read a feed of posts from the accounts they follow. Both Solidity and Rell handle this without much difficulty. Start with the Solidity contract.

Add a follow function that accepts two addresses: the user doing the following and the user being followed. The function emits an event that records this relationship. For now, both users are passed in as parameters. The authentication section later shows how to tighten this by relying on the authenticated user instead.

Solidity

```
event FollowUser(address indexed user, address indexed userToFollow);

function followUser(address user, address userToFollow) public {
    emit FollowUser(user, userToFollow);
}
```

In Rell, you define a `follow` entity that models a many-to-many relationship between a user and a follower. You then write a function that inserts a new row into this relationship table. As before, every piece of data stays on-chain in the dapp.

Rell

```
entity follow {
    index user;
    index follows: user;
    key user, follows;
}

// Then we add a follow method to follow a user
operation follow_user(user_id: byte_array, user_id_to_follow: byte_array) {
    val user = user @ { .id == user_id };
    val to_follow = user @ { .id == user_id_to_follow };
    create follow ( user = user, follows = to_follow );
}
```

The `follow_user` operation first looks up the entities for both users. It then creates a `follow` record that links the user to the account they follow. You can shorten this by placing the user queries inline:

Rell

```
operation follow_user(user_id: byte_array, user_id_to_follow: byte_array) {
    create follow ( user = user @ { .id == user_id }, follows = user @ { .id == user_id_to_follow } );
}
```

## Fetching posts from followers

With the model and follow operation done, the next step is retrieving a feed from followed users. Solidity requires several steps for this. You first query the event log for `FollowUser` events that match the user's address to get the list of followed users. You then run a second query that loops over those users and collects their posts.

Solidity

```
const contract = new web3.eth.Contract(contractABI, contractAddress);

async function getFollowedUsers(web3, contract, userAddress) {
    const followEvents = await contract.getPastEvents('FollowUser', {
        filter: { user: userAddress },
        fromBlock: 0,
        toBlock: 'latest'
    });

    return followEvents.map(event => event.returnValues.userToFollow);
}

async function getPostsOfFollowedUsers(web3, contract, followedUsers) {
    let posts = [];

    for (const user of followedUsers) {
        const userPosts = await contract.getPastEvents('PostCreated', {
            filter: { user: user },
            fromBlock: 0,
            toBlock: 'latest'
        });

        posts = posts.concat(userPosts.map(event => ({
            user: event.returnValues.user,
            text: event.returnValues.text,
            timestamp: new web3.utils.BN(event.returnValues.timestamp).toNumber(),
        })));
    }

    return posts;
}

const followedUsers = await getFollowedUsers(web3, contract, 'userAddress');
const posts = await getPostsOfFollowedUsers(web3, contract, followedUsers);
```

Retrieving relational data this way is awkward. You can push the data into a relational database for the frontend to query, but that adds complexity and moves the solution toward centralization. Rell's relational model lets you do the same work efficiently on-chain. The following query returns every post written by users that the given user follows.

Rell

```
query get_posts_from_followers(user_id: byte_array) {
    val posts = (user, follow, post) @* {
        .id == user_id, // Join on user id
        follow.user == user, // Join on who the user follows
        post.author == follow.follows // Join on posts for who the user follows
    } (
        post.timestamp,
        post.content,
        user_id = user_id
    );

    return (
        posts = posts
    );
}
```

The query uses joins to collect all the data in a single pass. Because Chromia's blockchain is relational and built on PostgreSQL, this query runs very efficiently. This example begins to show the advantages of a relational blockchain on Chromia. The next section covers authentication in Solidity and Rell.

Written for this site from Chromia’s public course. Code samples are the course’s own.

[← Previous**Create a news feed dapp**](https://chromia.com/learn/chromia-for-evm-developers/news-feed/)[Next →**Summary**](https://chromia.com/learn/chromia-for-evm-developers/summary/)

On this page

* [Fetching posts from followers](#fetching-posts-from-followers)
