Chris Nicholas

3.3K posts

Chris Nicholas banner
Chris Nicholas

Chris Nicholas

@ctnicholasdev

Developer experience @liveblocks • Interactive articles on https://t.co/alFrgXHV7f 🌱

🇬🇧 Katılım Temmuz 2020
872 Takip Edilen4.7K Takipçiler
Chris Nicholas
Chris Nicholas@ctnicholasdev·
And that's really all you need! If you'd like to download this Linear-inspired demo, I've just merged it ↓ lblcks.io/VReCa9O
English
0
0
2
51
Chris Nicholas
Chris Nicholas@ctnicholasdev·
On the front end, add `useOthers` to fetch your list of connected users—your agent will be amongst them. This snippet creates a simple avatar stack of connected humans/agents.
Chris Nicholas tweet media
English
1
0
2
64
Chris Nicholas
Chris Nicholas@ctnicholasdev·
AI apps have a flaw—agents are a black box. It's frustrating when an agent edits your document, and there's no way to tell what changed. You can't trust it. And the problem only compounds with multiple agents. We can solve this with real-time presence ↓
English
2
2
27
1.2K
Chris Nicholas retweetledi
Liveblocks
Liveblocks@liveblocks·
Create multiplayer agents with realtime presence. Trigger live presence from within AI workflows, highlighting actions to connected users, and making agents real participants instead of background jobs.
English
1
1
5
407
Chris Nicholas
Chris Nicholas@ctnicholasdev·
@simeonGriggs Sort of, but you don't always need to append a character! Sometimes the halfway point has the same amount of characters, e.g. like how the middle value between `0.1` and `0.3` is `0.2`
English
0
0
1
24
Chris Nicholas
Chris Nicholas@ctnicholasdev·
One more trick—drop decimal entirely, and use base 96. Indices become single ASCII characters like !, %, ). They sort lexicographically with no custom comparator, and a base 96 character can slot between any two decimal digits. Same precision, but a fraction of the size.
English
2
0
12
465
Chris Nicholas
Chris Nicholas@ctnicholasdev·
@simeonGriggs Thank you! Hard to explain in one sentence, but inserting between `!` and `/` will give you the halfway point `!>`. It's similar to saying what's between `0.2` and `0.3`? It's `0.25`. A live demo is in this section :) #base-96-in-practice" target="_blank" rel="nofollow noopener">liveblocks.io/blog/how-crdts…
English
1
0
1
16
simeonGriggs
simeonGriggs@simeonGriggs·
@ctnicholasdev Awesome thread! I've used LexoRank for this before, but using base 96 sounds way simpler. But what does it look like to insert an item between two here?
English
1
0
1
10
Chris Nicholas
Chris Nicholas@ctnicholasdev·
At @liveblocks, we provide APIs for building collaborative apps—all of this is already built into our `LiveList` primitive, which you can use directly in JavaScript and React. No worrying about servers, connections, realtime, it all works automatically!
Chris Nicholas tweet media
English
1
0
6
417
Chris Nicholas
Chris Nicholas@ctnicholasdev·
Real apps push to the end of lists constantly, which causes new indices to balloon into long strings. At Liveblocks we use viewport-based growth—when the last item needs another digit, we jump by 3 chars and then increment by one. Indices stay tiny. 0.8 → 0.9 → 0.9001
English
1
0
4
409
Chris Nicholas
Chris Nicholas@ctnicholasdev·
Creating a multiplayer list is trickier than it looks. When two users make simultaneous edits, state drifts out of sync—you can't just use a regular array. Real-time tools like Figma and Liveblocks use a specific technique to solve this. It's called fractional indexing ↓
English
3
10
201
12.3K
Chris Nicholas
Chris Nicholas@ctnicholasdev·
Decimals only work in theory. Floating point decimals runs out of precision after ~50 inserts at the end of the list, as you can see below. Storing indices as strings fixes that, but we've still got another problem—indices keep growing.
English
1
0
6
414
Chris Nicholas
Chris Nicholas@ctnicholasdev·
What if Alice and Bob both pick the exact same fractional index, say `0.75`? It stops working. The fix: give every user a unique ID and append it to the index. Alice's `0.75` becomes `0.75-001`, Bob's becomes `0.75-002`. No two indices can ever collide.
English
1
0
5
455
Chris Nicholas
Chris Nicholas@ctnicholasdev·
Because each position is independent, concurrent edits just work. Alice and Bob can insert, delete, and reorder at the same time—each op only updates one index, and both clients converge on the same list. No cascading updates, no conflicts. There is an edge case though…
English
1
0
6
483
Chris Nicholas
Chris Nicholas@ctnicholasdev·
Fractional indexing flips the model. Each item carries its own position value—a decimal between `0` and `1` that sits between its neighbours. Insert an item between `0.1` and `0.5`? Pick the halfway point, `0.3`. Between `0.1` and `0.3`? It's `0.2`. There's always room.
English
1
0
10
539
Chris Nicholas
Chris Nicholas@ctnicholasdev·
It gets worse when two users edit at once. Alice inserts an item, Bob deletes one. Both clients are working from their own local array, so when their changes merge, they end up applying ops on top of different states. The list diverges.
English
1
0
6
687
Chris Nicholas
Chris Nicholas@ctnicholasdev·
In a normal array, each item's index comes from its position. Insert one item near the start, and every item after it gets a new index. Locally that's fine. But in multiplayer, every shifted index is a message that has to travel over the network.
English
1
0
12
754