Live data from Hacker News

How to store your app's entire state in the url

scottantipa.com

51–60 of 416 posts

Re: How to store your app's entire state in the url

#51

It's pretty common to do this using the URI fragment in a link. For example: https://themeasureofaplan.com/market-timing/#initialContribu... This shows the performance of a market timing strategy on the S&P500, where you invest $20,000 upfront and $1,000 per month thereafter, while only buying when the market is 25%+ away from the all-time high price (analysis from 1993 to 2023). These user input variables are all di…

Interesting. Just to make sure I understand — that url contains all of the IDs and user inputs, and then you parse out of the key/value pairs and feed those inputs into the app?

Yep. See here for an explanation: https://stackoverflow.com/questions/12520124/parse-url-fragm...

Edit: better link to explain the concept

Re: How to store your app's entire state in the url

#52
I built a quick/wip payroll validator [0] that can read state (i.e. payroll details) from the URL.

The purpose in this case was to generate a QR code, the idea is this can be included in physical payslips. Then the numbers behind the calculations (tax deductions) can be validated, broken down, and understood. I'm developing more tools to these ends, via my overarching project calculang, a language for calculations [1].

I also have a loan/repayment validator [2] but haven't added this QR code feature yet.

Bank letters e.g. "Interest rates are rising and now we want 100e more per month, every month" could use a QR code to an independent validator or to see the workings behind the 100 calculation.

Not using this in the real world now and there are security considerations to keep in mind, but reading state from a URL facilitates the usecase: QR codes that link physical numbers to their calculation and model.

Implementation of payroll calculator is an Observable notebook and thankfully it neatly supports all my strict requirements as demo of this.

[0] https://observablehq.com/@declann/payroll-playground-ireland...

+Feature tweet: https://twitter.com/calculang/status/1608183731533107206

[1] https://github.com/calculang/calculang

[2] https://observablehq.com/@declann/loan-validator-dev

Re: How to store your app's entire state in the url

#53
This is a handy trick that I've used on multiple occasions. However, it may not work on some corporate networks that filter URLs with more than a certain number of characters (I've encountered limits of 2048 and 4096 characters).

The rationale being that long URLs are often suspicious and could potentially be used for SQL injection or path traversal attacks. Whether or not this is a good heuristic is left as an exercise to the reader.

Re: How to store your app's entire state in the url

#54
I'm not into web "programming", but do people really have to abndon binary data storage these days? I think compressing more informaiton produces still more information. While JSON is by no means as heavy as, for example, XML, it's far heavier than just array of int graph[x][y];

Re: How to store your app's entire state in the url

#55

This is pretty common and has a bunch of advantages, like the fact you can link to and bookmark a particular state. Also, if you are careful you get undo and redo for free with the browser's back button doing all the work for you. The disadvantages are that your representation of internal state becomes part of the interface - if you ever change your app you need to deal with versioning the state so your new version c…

> If your app has a server component that acts on this state, be super careful about acting on it and treat it as you would any other input under user control.

I would recommend signing it if it's generated by the server component, and checking the signature when the server component is provided this signed state.

For example to do this in Node is quite straightforward.

Key generation:

    const crypto = require('crypto');
    
    crypto.generateKeyPair('ed25519', (e, pubkey, privkey) => {
        // save pubkey and privkey somewhere
        // ...
    }
Signing:

    const data = Buffer.from(JSON.stringify(state));
    
    const signature = crypto.sign(null, data, privkey);
    
    const signeddata = `${data.toString('base64')}.${signature.toString('base64')}`.replace(/=/g,'');
Verification:

    const parts = signeddata.split('.');
    
    const data = Buffer.from(parts[0], 'base64');
    const signature = Buffer.from(parts[1], 'base64');
    
    if (crypto.verify(null, data, pubkey, signature)) {
        // signature not verified, throw or return
        // ...
    }
    
    const state = JSON.parse(data);
As the above uses Ed25519 the signatures are quite small too. It needs a bit more error checking, and might need extras like expiry time and such, but should be roughly sufficient.

Re: How to store your app's entire state in the url

#56
post #54

I'm not into web "programming", but do people really have to abndon binary data storage these days? I think compressing more informaiton produces still more information. While JSON is by no means as heavy as, for example, XML, it's far heavier than just array of int graph[x][y];

To put it into a url, you'll still need to serialize to text, even if the underlying data is binary.

Re: How to store your app's entire state in the url

#57

It's pretty common to do this using the URI fragment in a link. For example: https://themeasureofaplan.com/market-timing/#initialContribu... This shows the performance of a market timing strategy on the S&P500, where you invest $20,000 upfront and $1,000 per month thereafter, while only buying when the market is 25%+ away from the all-time high price (analysis from 1993 to 2023). These user input variables are all di…

This is a terrible example though, there is no reason why those shouldn't be normal query parameters.

I don't see why normal query parameters (using ? symbol) would be better than putting the key/value pairs after a # symbol.

They both achieve the purposes of allowing custom URLs that bring the user to a specific state of the app.

Re: How to store your app's entire state in the url

#58
In React you normally create local ephemeral state like this:

    const [myState, setMyState] = useState(null);
I've created at least 3 libraries that follow that same pattern, but instead of ephemeral the state is saved somewhere:

    // ?firstname=
    const [firstName, setFirstName] = useQuery('firstname');

    // localStorage
    const [name, setName] = useStorage('name');

    // global state (that can be connected to other places)
    const [user, setUser] = useStore('user');

Re: How to store your app's entire state in the url

#59
post #54

I'm not into web "programming", but do people really have to abndon binary data storage these days? I think compressing more informaiton produces still more information. While JSON is by no means as heavy as, for example, XML, it's far heavier than just array of int graph[x][y];

A colleague has been tasked with writing a remote image viewer. It’s slower than before (running on the same machine) “because it’s client-server”.

Naturally, the 16 Megapixel images are sent as an array of json floats…

Post reply on HN