New todo blocks!
Been wanting to improve the inputs in Clew for a bit now. Rolling it out to the todo block first, before we start using it in more places.
It’s built on top of tiptap, which is an excellent base for an editor. Combined with a few features we laid on top of it, this new input has a lot of neat features:
- Dates will be automatically parsed into due-date for todos
- @mention folks; which send a notification
- Reference tags by simply using #hashtags
- Rich styling (varies depending on use)
Turns out users loved the Canvas layout and getting rid of it for something that adds more structure was quite unpopular.
Reworked a few things over the weekend to give users the choice to pick what type of View they want to create – for now: Kanban or Canvas.
Our goal with Clew is to build better tools for digital work, and part of that means building something that works for different people, doing different types of work within the same team or company. This feels like a step in the right direction!
Someone in the audience screams: “the user is always right!”
Launched a new Kanban-style layout for Clew today.
A large part of the motivation around this was to make Views simpler to create, navigate and understand while still holding onto some of the flexibility that the canvas layout offered.
It’s easier to navigate and move things around and makes the UI feel more in-place and natural. The columns help keep Views more consistent across use-cases and devices; hoping to allow users to resize them and add margins to bring back more of the flexibility soon.
Spent the last few days cleaning up Clew’s backend codebase. Made it a bunch nicer and cleaner to work on in the future. Code from deprecated features, old models, database tables, and controllers all just add a lot of overhead to your thinking if they are no longer relevant. I hesitated on a good cleanup for the better part of a year, primarily because we just wanted to keep pushing forward, so it’s finally nice to see the cleaned up end result.
- No matter what size company you work at, or what your roles is, or how many users you have; it’ll always still feel daunting to run migrations that delete or change databases in any way. Felt like a madman running all the migrations on our production databases. But really, there’s no point worrying about it if you test it on a development database beforehand, take some backups, and have a good idea of how to roll things back if something goes wrong (always have a way to roll things back).
- The backend codebase is about 200,000 lines of code, that doesn’t really much on its own, but based on commits, that’s the result (diff) of about 1.3 million lines added and 1.1 million lines of code deleleted over the last 2-3 years. I hadn’t looked at it in a while and it surprised me a bunch… but it does make sense given the number of times I’ve re-written the codebase through various pivots. You throw away as much as you create.
I don’t talk about the full picture of Clew a lot of the time because it’s usually something that only investors and people who want to work on Clew are interested in. It was fun to pull out all the jargon to create this for our future pitch-deck.
Personally it makes me appreciate all the work that’s gone into Clew over the last year or two. Hard to maintain this perspective all the time when you’re always bogged down in details.
Building nice previews for Views. I’m using a scaled down and lighter version of the same rendered to generate these.
Probably want to do this server-side in the future and cache actual images for this use. It’s less performant to generate them live, but on the plus side, they’re always up-to-date so it’s fine for now.
Improved scrolling behaviour so that folks can scroll how they’re used to when viewing a canvas. This seems straight forward, but when you have scrollable blocks within a canvas that has to mimic its scroll based on mouse movements, things get funky when the user tries to scroll within a block and they both (the canvas and the block) scroll at the same time. Plus there is no straightforward or performant way to know what the user is trying to focus on.
The short answer was to prioritize canvas scrolling since it’s much more common. When the user wants to scroll within a block they need to tap/click the block in order to shift focus to it and scroll just within the block. Scroll focus goes back to the canvas when the user tires to scroll over the canvas again.
- Well designed, responsive and pretty customizable
- Complete (has all the essential features for a good forum)
- Active community around it
I’ve been looking for a good piece of software to do this, the first thing that came to mind was discourse.org, but I wasn’t able to get their opensource version running properly, which was when I came across Flarum. It seems like a more modern, lighter version of a forum.
It also looks like Flarum uses Laravel under the hood, so I should be able to write a package for it that allows users to auto-login via their Clew account.
I was a bit heads-down last week. Mostly been working on small improvements while doing some planning and research to build a recommendation engine for Clew. It’s going to be an important part of the service in the future so it has to work well and be sufficiently future-proof.
There’s a lot to consider when implementing a system that ingests and processes data, it’s easy to unnecessarily overdo these systems and waste resources. It’s also possible to build a system that won’t have much room to grow over the medium term.
I felt stuck with all the little choices for a bit, taking some time to learn more improved my confidence about building it.
I think it’ll be quite cool actually, I’m just calling them the “analytics engine” and “recommendation engine” for now. One service will ingest an asynchronous feed of data and track a few metrics. The recommendation engine will then use this data to output a few things like relevant views and updates based on what’s important to the user.
The new landing page went live today.
I think I finally got to a website that we could commit to, the ones before it felt like temporary pages we were holding back on until we launched. I personally find the process of making a new landing page quite important and fun. There’s a lot to learn from explaining the end-product to yourself until it makes sense and finally gets a pleasing flow of words for it. Then it’s just a matter of showing it to more people to see if they get it too. My co-founder does a lot of this too and often writes and rewrites a lot of the copy with better words and flow.
I find this helpful for the most part because in having to figure out how to talk to the people who’d find your product useful enough to pay for it, you learn a lot about what the product needs to be, and what’s important and what’s not.
So, all in all, the landing page exercise has been fun and useful, but back to working on the app tomorrow.
Spent the last few days working on improving the performance and UX of the canvas.
We launched the initial canvas two days before launch and I overlooked some UX that could’ve made the canvas faster and more natural to use.
On the graph above; the thick yellow/purple area I’m hovering over is where the drag happens. Below it you can see the (mousemove) events that get handled around it. The target is to get this to a point where re-renders happen only for the components being moved, without triggering any state or prop changes that trigger unceccessary re-renders on anything else. In this case it started with making the mousemove handler as efficient as possible.
The last few days of work got the canvas (zoom, pan, pinch + drag) at least 50% faster with more natural interactions. There’s more to go, and I’m exploring some interesting tricks:
- Global context for Views; which can help minimize prop changes being passed to child components, which prevents unnecessary re-renders.
- Indirectly updating stylesheet without triggering re-renders. Since all these movements are style changes, being able to change it without triggering a re-render could yield a significant performance improvement. Found this neat snippet that shows how this can be done: https://gist.github.com/alexreardon/77933916fdce05ed3406b631425c8e08#file-dynamic-style-tag-js
Wrapped up some more of the work on snapshots. This is going to be important for anyone doing serious work with Clew so I’m erring on the side of robust. Still need to build the ability to restore a version.
Something nice that’s coming out of this is the scaled-down canvas previewer. I’m hoping to re-use this to create cool previews for views.
This was the final version y’all! So badly want to do more with this!
Besides this delightful gif kicking up some dust on twitter, today was mostly a thinking day for me. Mostly looked through all the feedback and created some lists and thought about how best to approach all this. Also! Now we get support requests! Fun! xD
Sidenote; I expected the feedback to be consistent? As-in if something is bad or buggy I was expecting to hear about those things more consistently from more people. It surprised me what different folks thought was a problem. We got a wide range of feedback going from themes to entirely new feature suggestions and odd bugs. It quickly gave me a lot to think about and prioritize. I’m not complaining, this is progress and it’s good to know everything we need to improve, it just surprised me a little and felt a little overwhelming.
I think in moments like this it’s important to take a breath and put it all into context with what your vision for the product is, and then go from there.
This isn’t done yet but I’m very excited for when it is!
Worked with two freelancers on fiverr to get this done. One made the model out of the logo and the other is a cool animator who’s going to bring it alive for us! We’re working on adding some blinking + better background + lighting.
This is mostly for fun, but it’s good inspiration for when I want to code this in for our version of clippy in Clew.
Finally sharing Clew publicly has been really nice! I have a persistent and ambient feeling of “it’s not ready” in my head when building things, so I’m really glad this went well.
It’s wild how quickly the feedback and suggestions have poured in. Hopefully, I’m keeping up with it, it’s been a very busy day for the CI. The main thing I want to keep improving is the canvas, I shipped a bunch of improvements today, but there’s more to go for sure!
Kinopio’s canvas inspires me a lot @pirijan! The interactions are so satisfying and natural! So well done!
Need to add zoom + a better way to pan around the canvas; I went with [space] + drag because I’m so used to it in things like Photoshop, Figma and whatnot, but more than a few folks had no idea how to use it; going to have to think more about this or find add a nice way to teach new users about it.
The launch is still underway I suppose! Product Hunt is nice in that their audience seems to be pretty evenly distributed across timezones; so you basically get a 24hr drip of traffic. I’d always recommend folks do a PH launch considering there are a lot of passionate users on there; consumer products that appeal to general audiences tend to do better, that’s for sure! I should add that you do get a fair amount of users who just signup to check out the product with low intent; regardless, it’s good exposure and you learn a lot from it either way.
We’re launching Clew on ProductHunt tomorrow! I’m beyond excited and a little nervous.
Spent the day improving onboarding and other bits and pieces I felt needed a little touchup. Caught a few bigger improvements I would have liked to see in the canvas editor but I don’t think I have enough time to build + test for tomorrow. Plus, I feel it would be a mistake to rush, it works well enough for now and I can get to it more thoughtfully later in the week.
Everything seems buttoned up, I tested it all day. We’ll find out tomorrow!
PS; I turned on signups a few hours ahead of the launch (since it’s happening at like midnight); if anyone wants to try you can just signup now at clew.ai. @vin suggested we let early users have 2-3 letter usernames; I thought that’s a nice idea, so feel free to have that those early! :)
Added a good delete-account process. We always hope folks don’t get to that point, but if they do, then the process needs to be clean and easy.
One of the best examples of a great delete-account process I’ve heard of was in Basecamp 4. The idea is to have destructors (self-delete) on all resources so individual models can take care of cleaning up everything under them (related models, caches).
So when a user initiates a delete, we call delete on the User model, and before deleting itself, it cascades down through resources they directly own and calls delete on all of them before finally deleting itself.
Spent a lot of time thinking about Clew yesterday. I think I’ve narrowed down the 3 main areas I want to be working on over the next few weeks.
1/ There needs to be a better & faster way to get to your recent work. Whether it’s a recent canvas you worked on or something like a conversation block within a canvas you participated in. The “daily desk” is how most people get to their recent work today, but it’s a [click → daily desk → scroll down → click] process. This should be a 1 step interaction since people use it a lot. Maybe the cmd + K search bar should default to recent.
2/ Notifications need to improve. Grouped by day → grouped by canvas → grouped by block. I think this hierarchy needs to exist when surfacing notifications to keep things sane and help folks quickly get to updates they need, and avoid the rest easily.
3/ The (.ai part of Clew) / assistant. Part of the original concept was for Clew to be the all-seeing eye for your work. I wanted to use the “Clew” persona within the app to remind users of changes to the app, tips and more relevant updates. This is going to be very experimental but I think it’ll give the app more personality if we get it right, and gives us a clean way to teach folks how to better use Clew. (A little like Clippy from the old office suite; but better).
Buttoned up all the media stuff; launch video, things we need to launch on various sites and forums. Will likely launch 16th or 23rd. It’s an exciting and nervous feeling, I’m so intricately familiar with the whole thing that all I see is everything I want to improve and add. But I think it’s ready enough and definitely time.
Going to spend the next few days improving onboarding and testing lesser-used features on the app.
Spent the evening adding backup snapshots for documents. Stores a snapshot every 5 minutes while you’re in edit mode, going 75 snapshots back. This will work well for now, already thinking of an incremental backup concept for later.
I need to think about how many snapshots are reasonable too, I think 75 is likely a bit too high.
It runs on the backend for now, will add a UI to surface them to users tomorrow; so you could easily jump back to any of the snapshots or create one yourself.
Messages like this give me nightmares lol. My co-founder got this from a friend who used Clew for their schoolwork a few months back; we changed our underlying document model (now v2), and that caused a bug in v1 docs from a few months back. It was a superficial bug (just front-end) but really lit a fire under me last night.
The fix was pretty quick and she was able to access all the notes, but it’s a good reminder! 😅
Going to implement a robust version history for docs and double-check the process for retrieving backups today because I can’t stop thinking about it.
We actually call this feature slack-in-a-box lol; the entire idea here is that you can place conversations right next to the actual work; in context, in plain view. Under the hood the conversations are linked to the content on the page; so if you search for either – they’d show up as linked (like shown below).
Clew tech stack
Quick overview of the different applications and services that make up Clew.
If you’re building something and have any questions; get in touch! I’m happy to share what I’ve learned over the past two years.
- Laravel PHP application
- REST API
- 100% Serverless (AWS Lambda via Laravel Vapor)
- Last month Clew’s backend served over a million API calls for the first time with a response time under 150ms for most (>70%) requests
- Web sockets (we used to run our own turn servers but now we use Pusher)
Integration service; a single abstraction for utilizing data across integrations like Google Drive, Dropbox, GitHub, Figma, etc. It’s a serverless application written in PHP that can simultaneously search across dozens of integrations in seconds, milliseconds, if you take into account the caching layer that accounts for external latencies. The API even listens for updates on any resource it has access to; these can be used for consolidating notifications on the front-end.
AREST backendthat serves graph-like content among other resources and can manage, authorize, tag and keep track of any content. It facilitates a central repository for all your work—data from all your tools, in one place, in one unified, consistent and reliable API.
- Next JS
A progressive web application (PWA)written in Next JS and deployed to serverless with CloudFront distributions close to all our core users. Almost all pages on Clew score a 100% performance score on Lighthouse; mostly have to thank Next JS for this.
The landing pages are separate frontends that I usually just write in plain HTML + CSS, just because they change a lot and don’t stay around too long. Just needs to be fast and pretty.
Over the last decade, our work has moved to the cloud. Alongside the benefits, we see work happening across a growing number of disparate, sometimes redundant tools. Files and data have gotten siloed, adding an additional layer of complexity to collaboration. Today, we write documents in one tool, track projects in another, communicate on Slack, design in Figma, and the list goes on.
Remote work (as much as we love it) has amplified the problems we have with today's digital workspace. Without a robust organizational system, having to collaborate across the boundaries of different tools and content created by different people, induce friction on all our workflows. It's no surprise knowledge-workers are estimated to spend upwards of 20% of their work hours just looking for information.
You’ve likely felt, first-hand, some of the shortcomings from this style of work:
- There's no easy, straightforward way to organize and utilize different types of information, from multiple sources, in one place.
- It's hard to trace work to the context in which it was created, either as an audit trail or for future work.
- It's impossible to retain context across different work that reuses some or all of the same knowledge.
- It's impossible to search across all knowledge, from one place.
We pay for these shortcomings by wasting time hunting for what we need and relying on people to give us context or to point us in the right direction. This is a leading cause of information overload and stress at work.
What is Clew?
Clew is where work comes together—work sprawled across disparate tools, work lost in chat threads and emails, work floating around with no context or home. Clew is the traditional knowledge management tool, wiki, and what have you, reimagined. It’s a better way to organize work for the individual and the team. For any thought or project, Clew captures the context, surfaces what’s needed, and preserves what’s important.
Clew's system creates a central source of truth that's highly searchable and easy to navigate. The relationships between pieces of content and people may be rich and complex, but a user’s experience creating, sharing, and finding information is designed to be effortless and delightful.