Inspiration

The inspiration for Tagly was from one of the highest voted feature requests on the Microsoft Teams UserVoice: https://microsoftteams.uservoice.com/forums/555103-public-preview/suggestions/16929583-support-hashtags-in-channels-and-dms

The original request was made in November 2016 - over 4 years ago. Despite numerous updates from MS saying that the feature is on the backlog and that they would keep everyone updated, it doesn't seem to be a high priority for them.

Which is strange as, if you read through the 320+ comments, you can see that it's an issue that people are very passionate about, and there are numerous instances of people saying that the lack of it is blocking their adoption of Teams, or that they're moving back to Slack, etc.

After reading that there was some new MS Graph subscription endpoints that would make the idea feasible, I decided to see what I could do to add #hashtag support myself.

What it does

Tagly has two parts, a Teams App on the front-end, and a server component on the backend.

Once it's configured for a tenant, the server component creates a subscription to listen for change notifications for the channel messages in a tenant (ChannelMessage.Read.All)

Once it has this, it can see new messages as users create them. If it detects a hashtag in the message text, then it replies back^ to that message on behalf of the user with a special Teams deeplink, that will open the Tagly app in Teams and pass some context through so that Tagly can detect the hashtag that the user has clicked on.

(^Ideally, it would PATCH the original message instead, to markup the hashtag with a link in place, but there's no support for that in the Graph currently - although I did see a reference somewhere that hinted it might be possible in the future. Currently PATCH support is limited to setting a DLP flag only.)

The app then shows a new column, filtering all the channel messages the user has permission to see against that tag, and any other messages containing that tag will show up.

The UI for the app takes inspiration from Tweetdeck for Twitter, which works in a similar way, and is a popular tool for Twitter power users.

Once I got hashtags working, I realised that I could add filters for various other attributes a user might be interested in as well, so added filters for various types of messages (e.g. containing attachments / images, etc), who sent the message and who is mentioned in the message, and which Team or Channel the message is in.

How I built it

I spent a lot of time fleshing out the UI in React first, using the @fluentui/react-northstar Teams UI framework. I used mock JSON data I obtained from the MS Graph Explorer site using Mirage JS, and iterated against that until I had the UI roughly working.

I then turned to actually getting it working against real data in the backend, which wasn't as straightforward as I'd hoped, but I got there in the end. I applied for a Office 365 Dev tenant, and used that to develop against. The Dev tenants have a useful set of sample data packs which help you start of with some sample users, who helpfully match the same ones on the Graph Explorer tenant. However, the sample data doesn't include any Teams data at this stage, so I had to setup some scripts to generate some sample Teams data myself.

The other thing I had to keep in mind was that given the very sensitive nature of being able to read all of a tenant's channel messages, it was imperative to design the solution so that it could be deployed as an Azure Marketplace app that a tenant will install inside their own Azure Virtual Network. So we can never see any of their messages, its all secure inside their own Azure instance.

Challenges I ran into

  1. Lack of sample data for Teams
    • As mentioned above, there are no sample data packs for Teams data that you can add to an Office 365 Dev tenant, so I had to come up with my own scripts.
    • I ran into a lot of issues while doing this with trying to add data in "migration mode", which is a special mode you can put a new Team into and import messages while setting the timestamps to a specific time. I found an associated GitHub issue, and it was recognised as a bug and supposedly sorted, but I'd changed to just use the normal POST message endpoint by then as I realised I wasn't that bother about the timestamps on my messages for testing purposes.
    • Importing sample data is still harder than it could be though. There doesn't seem to be a way to add an array of messages in one go, as opposed to calling the POST message endpoint for each new message at a time. I think the migration story for importing Teams data could do with more work, not sure how they'd expect a bit organisation to migrate from Slack with the way it stands currently.
  2. Graph permissions
    • I found trying to figure out how to set the right Graph permissions at an application level to be pretty confusing.
    • Additionally, some of the Graph endpoints I'm using are currently classified as "Protected", so I needed to request access. Luckily it didn't take too long for the access to be granted.
  3. Some issues with some of the @fluentui/react-northstar controls.
    • Some of the controls I wanted to use didn't work how I'd expect them to, in particular the Dropdown control. I raised a GitHub issue about it, but gave up and and restyled the open source react-select component instead.
    • On the flip side, most of the controls were really good and gave me a big head start, particularly the Chat component.
    • The FluentUI components seem to in a bit of flux at present between the Teams ones (Northstar), and the main Office 365 ones, so it will be good once they're merged together into a single framework.
  4. Byzantine MPN approval process
    • By far the biggest and most drawn out challenge has been just trying to get approved on MPN.
    • I created a Ltd company in the UK, which requires fairly rigorous levels of KYC (Know Your Customer) approval, and after getting my incorporation certificate and company number and checking that it was listed on the UK Gov Companies House register, I applied for MPN.
    • It came back with an "Account Verification failed" error, with no useful details. The error details said to open a support ticket and add verification documents, which I swiftly did. And then waited. And waited. And waited.
    • I requested if the Devpost team could assist (https://microsoftteams.devpost.com/forum_topics/34732-mpn-application-stuck-in-pending-state), and Stef was very helpful, but there was still no response.
    • The ticket was escalated to someone at "Tek Experts" who brought in the Partner Escalation team and the Senior Relationship Manager as well. And still no progress.
    • Which brings us to today, where after busting a gut to get everything completed by the deadline, and after many late nights and lack of sleep, I go to submit my app to Appsource only to get the error message: "Your account is not currently eligible to publish to the marketplace."
    • So all my effort and hard work seems to have been for nothing...

Accomplishments that I'm proud of

Having everything completed in time for the deadline - just! And for solving a problem that a lot of Teams users have complained about and making a tool that I think would make users a lot more productive in Teams.

What I learned

I learned a lot about the @fluentui/react-northstar Teams UI framework, which I'd not used before. Fairly positive experience overall.

I also learned a lot about MS Graph, again which I'd not used before.

What's next for Tagly - #Tag your Teams

Depends on if I ever get approved for my MPN application or not I guess...

There's a long list of features planned on the https://tagly.app/ site:

  • Message Action support
  • Calendar, Planner and To-do tasks support
  • Reaction support
  • Workspaces
  • Configurable views
  • Activity Feed and Desktop Alerts
  • Power Automate integration
  • Viva Topics support
  • Sharepoint Term Store support
  • Admin managed filters
  • Analytics / Power BI integration
  • $Cashtag and user defined tag support
  • Full text search support
  • DLP integration
  • Chat message support

Built With

Share this project:

Updates