67 ms·
How to store your app's entire state in the url
- _ea1k 4y agoThis reminds me of ASP.Net's viewstate feature, tbh.
- escot 4y agoHey all, I made this post to show a technique that I'm using in my keyboard-centric flowchart editor [0]. I really love urls, and the power that they hold, and would love to see more apps implement little hacks like this. Also, another shout out to mermaidjs and flowchart.fun for also implementing similar url-based sharing. [0] https://www.knotend.com https://www.knotend.com
- tlarkworthy 4y agoThere is a size limit though that quickly gets exhausted if you are storing text (2000 chars)
- rmetzler 4y agoThis is the right answer here. The solution works until it doesn’t. Browser URLs are limited in real life. So when the state grows it will break sooner or later. Of course it depends on the usecase.
- tonerow 4y ago(maker of flowchart.fun here) This is technically true but it's a little more nuanced. The 2048 character limit comes from Internet Explorer. There's a great answer on SO https://stackoverflow.com/a/417184/903980 https://stackoverflow.com/a/417184/903980 Still on FF I opted to use LZ Compression (pretty sure many other sites do this as well) to get the number of characters down
- tlarkworthy 4y agoI have done this myself and various tools e.g. slack, Twitter will truncate long urls. Eventually it will break somewhere, not just in the browser. If your tool has a hard limit on information content it's ok, but that does not seem to be the case here.
- escot 4y agoYou're right, its a limitation. Knotend also supports upload/download of a .knotend file to get around this.
- __MatrixMan__ 4y agoStore the content in ipfs and just put the hash in the URL? I haven't used https://github.com/ipfs/js-ipfs https://github.com/ipfs/js-ipfs in this capacity but I'm under the impression that that's moving bits around like that is more or less its purpose. Although I suppose this puts a burden on the URL-creator to pin the content until the URL-clicker doesn't need it anymore, which is not how URLs are supposed to work.
- tonerow 4y agoLove the app!
- escot 4y agoThanks!
- bytesandbots 4y agoIf the schema is fixed, using proto buffers will greatly reduce the length required.
- gernb 4y agoLots of sites do this. Lately for me there's https://www.typescriptlang.org/play https://www.typescriptlang.org/play I'm mixed on it. It means it's mostly useless for having your own list of creations because you have to manually store the URLs (PITA) and you need to store them somewhere accessible if you want to repo the UX of the site actually storing them where you can more easily access them from anywhere.
- EGreg 4y agoIt’s actually difficult to do this in the UX. Suppose that you have a hierarchy that was opened. Do you want to store all the hierarchy breadcrumbs in case you hit refresh, and reload all of them? Furthermore, what about URLs to initiate an action from a particular context? If you refresh what should it show? It should show a dialog / lightbox above the page, showing the form / interface for filling out before taking this action.
- ddyevf635372 4y agoRoutes are the fundamental building blocks of a webpage, so the hierarchy will be represented by the routes in the url. Proper frontend framework, like Ember.js, built on top of routes and building a UX focused web app is much easier with them. https://guides.emberjs.com/release/routing/ https://guides.emberjs.com/release/routing/
- EGreg 4y agoYour link and the explanation there is not enough. It only shows the current resource you are looking at. As I said above - you should also consider representing the breadcrumbs of how you got there in the hierarchy (you could have taken multiple paths) and also on top of that use URLs to represent actions that can be taken in dialogs ! Here is a question for you: what happens when you have a url for a New Issue in github? By itself. It renders a form for a new issue full-page. But now what if I want it as an overlay over a hierarchical state that U navigated to? I should have a longer URL and it wouldnt be full screen anymore.
- ddyevf635372 4y agoOverlay is useful sometimes, however not always the best UX. The main route of the url (example.com/page/subpage) represents the background page of the overlay. You have two options. 1. Using further subroutes to represent the stage of the overlay if your framework supports it (Ember does) (example.com/page/subpage/form/step1). 2. Using query parans to store the state of the overlay (without the actual data of course): … subpage?overlay=form&step=1 Also breadcrumbs should always mirror the routes. Frameworks, libraries can automatically do it for you.
- EGreg 4y agoOn a related note … If you don’t want to store anything on the server, why serve the static JS and HTML? You can embed them in the URL also. In that cass the URL just becomes a local file. You should store the file locally, along with all the data it embeds. Or you can store the files on a CDN at the edge. The problem with the latter is that people can abuse the storage. Really, the Web needs to be overhauled to have a topology more like a DHT, where you only have peering agreements with a few peers, and they cache the content temporarily when it is requested a lot. So no centralized servers at all.
- redleader55 4y agoA better idea is to use the URI fragment (the string after the # sign). It has the advantage of not having a size limit, and not needing to be sent all to the backend during the request. `window.location.hash` is your friend.
- kishinmanglani 4y agoThat's really interesting. Do you have any idea how much data (i.e. max amount of json) you can store using something like that?
- bckygldstn 4y agoIt seems to vary greatly by browser. Based on this SO answer [1] MS edge only supported 2000 characters in 2017, while Chrome currently handles 40 million characters (of compressed, encoded json). [1] https://stackoverflow.com/a/44532746 https://stackoverflow.com/a/44532746
- G3rn0ti 4y agoWeirdly, with IEs it was exactly 2083 characters (1) not some base 2 number and MS never increased this number over all these years. This upper limit even included fragments. We tried to do something similar as described in the article and were surprised to learn about IEs limitation. In the end, we stored states on a JS object instead using their hash sum as keys and put that inside the fragment. Then fragment based navigation worked like charm across browsers. (1) https://support.microsoft.com/en-us/topic/maximum-url-length-is-2-083-characters-in-internet-explorer-174e7c8a-6666-f4e0-6fd6-908b53c12246 https://support.microsoft.com/en-us/topic/maximum-url-length...
- refulgentis 4y agoI don't quite understand and it's on me, trust me :) My reading is you were worried about length of encoding one state, so you moved to encapsulating states in a dictionary with keys of hash of State and objects of State And this led to a decrease in size of the URL? My guess at my misunderstanding: you kept the state dictionary server-side or at least some other storage method than the URL, and just used the URL to identify which state to use from the dictionary. I e. The bit you add to the URL is just the hash of the state, or dictionary key
- mrdoob2 4y agoMade this thing in 2010. I can't remember if I saw the trick being used in another website before or not... https://mrdoob.com/projects/voxels/#A/bnciaTraheakhacTSiahfaotaiafUscierhoShahfShahfafiWheSheUeWSfafhchhefffchhWffahherhpfXTbdUhUhUhVihShaffahfahhcfhYhaffYhahhaeeUhahhahhcdfShYhYhafhUheffdafhcjhShYfYfahfYfahfYfafhcjhYeahfShShWhfVbfdjjhaffaffaffafhafhafhahhahhahhahfahfeehhahfahfaffaffafhafhahhWhfahhWhfWffahhefXhUhehffahiaddbnfffYhcmfrfsaaiU https://mrdoob.com/projects/voxels/#A/bnciaTraheakhacTSiahfa...
- benatkin 4y agoThis has taken off in the Vue community w/ https://sfc.vuejs.org/ https://sfc.vuejs.org/ and https://uno.antfu.me/play/ https://uno.antfu.me/play/ and they use the fragment so it doesn't get sent to the HTTP server
- tlavoie 4y agoAs usual when I see this sort of thing, I have questions around the security needs of the application. Storing all of this information on the client means that the client has to be trusted to not mess with all of this state. If it's important, it needs to be stored and checked server-side.
- somehnguy 4y agoValidating data from the client should always be done on the server in that context, regardless of if state is being saved client side or not. I think this is just an extension of what you said though. I can think of many apps that don't need server side data storage or security that would benefit from this type of state saving however. For example, this app that I was using today - https://wheelofnames.com/ https://wheelofnames.com/ . Right now to save I need to create an account, presumably to tie my account to the saved state on the server side. That's pretty heavy/intrusive when all I want to do is keep the names list and preferences populated for my next visit.
- tlavoie 4y agoSure, there are reasonable use cases. It's worth pointing out where those use cases are not reasonable though, because those devs that don't know better will be inclined to treat obfuscated inputs as if they're trustworthy.
- deckard1 4y agoyep. A coworker introduced a CSRF doing this. I had to point out that you can't just take raw input from a URL and throw it back on the page. Even after I pointed it out and gave a proof-of-concept they still didn't get it.
- tlavoie 4y agoRight, that's usually when I go into story-telling mode, to paint a picture of exactly the sorts of things I'd be doing with the problem as an attacker. Technical vulnerability descriptions provide useful information, but people often need an idea of what it really means, to them.
- ladberg 4y agoI tried to do that at first with https://textshader.com https://textshader.com because the whole site is client-side and I didn't want to bother with a backend. It didn't really work because the state is unbounded in size, so instead I just chuck it on GitHub gists and then point to the gists. It means I don't have to store any data myself and there's zero recurring costs outside of the domain name... but if the site ever got popular I'd probably have to figure something else out.
- didericis 4y agoI dream of a world where there’s some kind of ipfs like thing for storing state in some sort of distributed commons, all while maintaining user privacy/allowing for state to expire if untouched, and monetized in a balanced way to incentivize hosting without discouraging consumer adoption too much/trending towards gouging. We’re so close/all the pieces needed seem to exist, but getting something like that off the ground is super difficult.
- AndrewStephens 4y agoThis 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 can transparently handle the old state format. 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. If you app is completely client side, consider storing the state in the #fragment section of the URL. This never gets sent to the server. An example from my own site [0] - see how the fragment part of the URL changes as you select different topics. There are also limits on just how much you can cram into a URL but with care you can shove a lot of state. [0] https://sheep.horse/tagcloud.html#computing https://sheep.horse/tagcloud.html#computing
- typingerror 4y ago> 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.
- 4y ago
- strongpigeon 4y agoHah, I came up with the same thing for https://fivethreeone.app/calculator https://fivethreeone.app/calculator . The reason I did the compression (using pako as well) was that without it the URL was too long to show a preview on iMessage. I also compress the state manually myself which saved a bunch of bytes too.
- deleted 4y ago[deleted]
- pjpweaver 4y agoI discovered when I hit a similar issue, that just putting a "-" character every 40 or so characters resolved the iMessage parsing issue. There may be a max URL length, but I hit it much sooner without the hyphens.
- hardwaregeek 4y agoI love doing this for playgrounds! It's so nice to be able to share a link with the code embedded. Especially if you're giving someone a bug report and they need a minimal reproduction.
- nerdponx 4y agoI appreciate this feature a lot on sites like https://tio.run https://tio.run and https://mermaid.live/ https://mermaid.live/. However the URLs also get very long and I often want to run them through a shortener for e.g. posting to IRC. But there are worse problems to have!
- swyx 4y agoThis is quickly becoming a standard in apps and it really shouldnt be handrolled since its such a common requirement and easy to get wrong (between serializing/deserializing/unsetting states). In Svelte it is now as easy as using a store: https://github.com/paoloricciuti/sveltekit-search-params https://github.com/paoloricciuti/sveltekit-search-params in general i've been forming a thesis [0] that there is a webapp hierarchy of state that goes something like: 1. component state (ephemeral, lasts component lifecycle) 2. temp app state (in-memory, lasts the session) 3. durable app state (persistent, whether localstorage or indexeddb or whatever) 4. sharable app state (url) 5. individual user data (private) 6. team user data (shared) 7. global data (public) and CRUD for all these states should be as easy to step down/up as much as possible with minimal api changes as possible (probably a hard boundary between 4/5 for authz). this makes feature development go a lot faster as you lower the cost of figuring out the right level of abstraction for a feature 0: relatedly, see The 5 Types of React Application State, another post that did well on HN https://twitter.com/swyx/status/1351028248759726088 https://twitter.com/swyx/status/1351028248759726088 btw my personal site makes fun use of it -> any 404 page takes the 404'ed slug and offers it as a URL param that fills out the search bar for you to find the link that was broken, see https://www.swyx.io/learn%20in%20public https://www.swyx.io/learn%20in%20public
- enos_feedler 4y agoSo you think of a new feature "X". That feature has a bunch of state it needs to manage. Each piece of state has _requirements_ over where it fits within this hierarchy based on how this state relates to the feature being developed. I don't understand where the cost lowering is? I know instantly where the state should live when I design the feature.
- swyx 4y agorequirements evolve over time. and they tend to go up in terms of persistence/auth/sharability needs. it would be nice to make that easy; and conversely when they arent needed anymore it'd be nice to take the state persistence level down with just a few character changes rather than switching state systems entirely
- devmunchies 4y agoSeems like it could be better to store the state in a database and create a unique, short ID that goes in the URL, especially if your doing server rendering (like SSR react or HTMX, or rails/Django) > I also didn't want to store anything on the backend (at least for the free tier). You can make the state unique in the DB by a user cookie ID and then upsert the state which will overwrite older state with the latest state. Then you only have 1 record per free user. Remove record that haven’t been modified in 30 days and you don’t have much overhead. Just off the cuff thinking.
- ErrantX 4y agoI am genuinely intrigued as to why that's better? Especially as in the second part of your comment you restrict shareability/usability significantly from what the author wants to achieve (IE I can't as a free user bash out a diagram and share it, then later do another and share with a different person). In fact the solution is so elegant when you think on it; free account volume is incredibly scalable, zero storage cost, offer immediate value but also a really simple upsell to pro accounts (save to the DB so you don't have to save the URls).
- devmunchies 4y ago> Especially as in the second part of your comment you restrict shareability/usability significantly no it doesn't. If my URL is `/thing#a1234` and I share it with you it will load my state for you. If you make a change, it's easy to push a new hash to the url that belongs to you. > I am genuinely intrigued as to why that's better? I didn't say it was better. We engineers are supposed to discuss solutions. I ended my last comment with "Just off the cuff thinking".
- kamikaz1k 4y agonot my fight, but you literally wrote: > Seems like it could be better Maybe you didn't mean it that way, but it does come across that way. Just a data point for you; I got no beef...
- mguerville 4y agoIsn't this also how old school games (I've seen it as late as the NES I think) did allow you to save progress, you'd get a short string as your "save" and could just enter it to restart the game in the same state later. I love that it offers essentially unlimited "saves"
- deleted 4y ago[deleted]
- jonny_eh 4y agoGreat YouTube channel about reverse engineering old game password systems: https://www.youtube.com/playlist?list=PLzLzYGEbdY5nEFQsxzFanSDv_38Hz0w7B https://www.youtube.com/playlist?list=PLzLzYGEbdY5nEFQsxzFan...
- colejohnson66 4y agoThe downside of a lot of those "password" save systems was that you lost your lives, and sometimes more. The password sometimes just wasn't long enough to store enough information. For example, Driver[0] (at least on the Game Boy) is an icon-based one with eight(?) symbols per field and four fields. That's only 12 bits. [0]: https://en.wikipedia.org/wiki/Driver_(video_game) https://en.wikipedia.org/wiki/Driver_(video_game)
- hot_gril 4y agoAnd you can use your save on another system.
- actually_a_dog 4y agoOnly about 20 years late: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...
- Zamicol 4y agoWe wrote a library for storing application state in the URL. Its novel feature is using fragment query, which prevents the information from being sent to the server. https://github.com/Cyphrme/URLFormJS https://github.com/Cyphrme/URLFormJS I would love to see it get more use. Here's a small demo: https://cyphrme.github.io/URLFormJS/#?first_name=Bob&last_name=Smith&email_address=bob@something.com&phone_number=1234567890&subscribe_latest_news=true&country_select=1:~:text=Bob https://cyphrme.github.io/URLFormJS/#?first_name=Bob&last_na... See my other comment on this page for some other examples of its use.
- notRobot 4y agoThis looks very cool, and I'll definitely use it in a side project sometime soon!
- lelandfe 4y agoDoes this necessarily prevent the ability to provide in-page anchors?
- vbezhenar 4y agoSince you're using JavaScript, you can implement anchors in the way you want.
- Zamicol 4y agoThe fragment query delimiter is `?` with `&` for between values, just like normal queries. It practice, browsers are not fragment delimiter aware so at the moment I would treat them as mutually exclusive. There's a larger issue of URL fragment delimiters. For a practical work around on Chrome only, fragment directive/text fragment can be used as a delimiter. (In my opinion, Chrome's delimiter should be re-worked with a new, more comprehensive delimiter.) Example of the workaround: https://en.wikipedia.org/wiki/URI_fragment#References:~:text=Bob?bob=bob https://en.wikipedia.org/wiki/URI_fragment#References:~:text...
- mperham 4y agoI recall this technique being used in 1999. It doesn't work well with caching proxies which key off the URL, using a Cookie header is cleaner and simpler.
- easrng 4y agoCaching proxies which key off the URL are pretty much useless now because they don't work with HTTPS.
- getToTheChopin 4y agoIt's pretty common to do this using the URI fragment in a link. For example: https://themeasureofaplan.com/market-timing/#initialContributionInput=20000&monthlyContributionInput=1000&gapToATHInput=25&cashInterestRateInput=2&tradingTransactionFeeInput=0&minYear=1993&maxYear=2023 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 directly encoded in the URL, after the # symbol.
- iLoveOncall 4y agoThis is a terrible example though, there is no reason why those shouldn't be normal query parameters.
- getToTheChopin 4y agoI 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.
- wildrhythms 4y agoAn often unintended side effect of using the URL hash to contain state is that it breaks potentially linking to an anchor element ID somewhere in the page. Obviously this doesn't matter much if the page doesn't use anchor IDs or you don't intend on users doing that.
- nimzoLarsen 4y agoInteresting. 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?
- 4y ago
- ecshafer 4y agoWhat is old is new again. Back before websites were "Apps", you could often do exactly this (Including Authentication!) right from the url.
- Zamicol 4y agoBefore cookies, I remember in middle school (ebay?) using the URLs for sessions. If they forgot to include the session token on any link on the page, you'd be logged out and have to authenticate again, or you could navigate backwards back to a sessioned address in your history. Once I figured that out, I copy and pasted my session id so if they omitted the session on a link I wouldn't have to log in again.
- tresilience 4y agoThis brings to mind the concept of continuation found in Seaside Smalltalk. https://www.seaside.st https://www.seaside.st
- sidharthv 4y agoI had to add compression into Mermaid live editor's URL state as the length limit was exceeded with big diagrams. Wrote this SerDe which can be extended with better algorithms in the future. https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/serde.ts https://github.com/mermaid-js/mermaid-live-editor/blob/devel... Eg: https://mermaid.live/edit#pako:eNo9kUGTnCAQhf8K1adNlesoqKiHVO3MbE7JJZNcsubACioVEQOYZHbK_76I2eUE_b3X3cW7Qau5gBp6w-YBfTs3E_Ln4ekoe_T96-ef6P7-IzrenbSajbAW_ZVuQDP7pT_symMQnO6OzApUZOhx2hr-h6cAz08XxcYxtIMIlDCKSe5n3jZVA24QSjRQ-ysXHVtG10C0Iyt-L2JqA73tPRtQ0hhtHlqnjd1Ax0Yronfqt2S9-KQnd5EvwYmzDa7NtPrxy8yZE49cejvUuxfY4vTlOrVQO7OIN9FZMv8t6l01s-mH1upN5J9Q3-Af1JiWMSY0wwXNaZniPIIr1BWO8zwnOKGkolmRrhG8BHsSU0LKskpKD3OaJV4vwkJf9jBCJhGMmnFhthnuOoeQpHW-3uqpk_1WX8zoy4Nzs60Phw3HvQ9oeY5brQ5W8oEZN_ypikOBi5JhIgpKWE4Ib5_TquxwlnacJilmsK7rK1fwoJI https://mermaid.live/edit#pako:eNo9kUGTnCAQhf8K1adNlesoqKiHV...
- tonto 4y agoI always like this when the url is always copyable, but in our app, the state can get quite large. We started with base64 encoded gzip of json.stringified app state but just gets quite long. Arguably it could be reduced a little bit, but would still be hundreds-thousands of chars routinely, so we switched to using a little URL shortening service that we wrote on aws lambda+dynamodb
- dndn1 4y agoI 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-wip https://observablehq.com/@declann/payroll-playground-ireland... +Feature tweet: https://twitter.com/calculang/status/1608183731533107206 https://twitter.com/calculang/status/1608183731533107206 [1] https://github.com/calculang/calculang https://github.com/calculang/calculang [2] https://observablehq.com/@declann/loan-validator-dev https://observablehq.com/@declann/loan-validator-dev
- cpa 4y agoThis 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.
- IYasha 4y agoI'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];
- recursive 4y agoTo put it into a url, you'll still need to serialize to text, even if the underlying data is binary.
- IYasha 4y agoyup. data > gzip > UU/B64/URL-encode > text.
- misnome 4y agoA 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…
- secondcoming 4y agoUnless it's still at a proof-of-concept stage, that person is out of their depth.
- misnome 4y agoYes, yes they are. Unfortunately this is dysfunctional academia, so as long as the people paying the bills (who know nothing about building software) like them, they remain at this depth. Extra fun fact: Two years into the project, they hadn't heard of REST. Then rejected it, because, I quote, "The S means stateless and [they] need the server to store state"
- IYasha 4y ago
- franciscop 4y agoIn 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');
- kevinfiol 4y agoMy favorite example of this is flems: https://flems.io/ https://flems.io/
- jonny_eh 4y agoNote that this could easily break or get messy as you make changes to your app. Consider either some kind of versioning indicator, or be very careful to only add fields, never changing them.
- michaelteter 4y agoAs long as your users are reasonably tech-saavy this is ok. But long URLs can be problematic when sent in email for many possible reasons, such as the email client wrapping the URL and then creating a link out of just part of the original URL. The user sometimes doesn't realize this and gets unpredictable results when trying to use the URL they "saved" in the email. Perhaps instead, assuming the user is online, hash the json state data, then send the json+hash to the server and update the URL to URL?hash. Then the user has a much shorter URL, and the server can lookup the json state from the provided hash to resume the app at that state. As a bonus you then have versions of the data over time (either posted automatically in the background or on-demand when the user clicks Save).
- m00dy 4y agoAnother one would be passing ipfs hash in the url
- generalpf 4y agoI remember when WebSphere Portal Server used to do this, and the URL would exceed 4096 characters, which was the limit that IE 6 (?) would support, breaking the entire site.
- markandrewj 4y agoThere is still a browser URL limit, I have hit it recently while applying a large number of filters to a search in Kibana.
- locofocos 4y agoNeat. I did this for a very basic react ratio calculator I built. My state was so basic and small, it felt fine for a toy project. Certainly a practice I would scrutinize in a production application, but it could be useful. https://locofocos.com/anything-ratio-calc https://locofocos.com/anything-ratio-calc
- lol768 4y agoAm I alone in thinking it's ridiculous for an editor action to push/pop state in browser history to allow undo/redo? Surely this leads to substantial browser history pollution?
- vasco 4y agoYou are not wrong. I cannot think of many interactions with an editor where if the user presses the back button they want to undo the last micro action they did, instead of going to the previous page / major UI interaction. Even just trying the demo after adding 3 blocks I had to press back like 5 times to exit the page back to where I was before.
- kccqzy 4y agoAbsolutely agreed. Given how HN can be when complaining about back button breakage (so common that it had to be explicitly banned), I'm surprised so few people are talking about the implications here.
- rickreynoldssf 4y agoYour SEO guy is going to throttle you if you even consider thinking about doing this.
- eatonphil 4y agoWhile this is great for being able to send anyone a URL to a stateful page without needing a backend database, keep in mind browsers have URL length limits and they vary by browser. Compressing as mentioned in the article can help but still you want to know when you're going to go over and figure out a plan for dealing with that.
- vbezhenar 4y agoChrome limits URLs to a maximum length of 2MB It's more likely that messaging app will have stricter limit than Chrome (and other browsers at this point do not matter). Though I'd suggest to use some kind of server storage if you need to transfer more than few kilobytes of data.
- eatonphil 4y agoGreat point too. At least you can count on being able to send over email. But yeah, the length will get long and even if the browser can handle it do you really want to be passing around that much text at once? I'm also curious what various OS clipboard size limits are.
- divbzero 4y agoApp state in URL can be a good idea, but if possible I prefer readable path/query parameters instead of unreadable base64 encoding. As one comparison, this is Google Finance encoding stock chart parameters: https://www.google.com/finance/quote/F:NYSE?window=5Y Versus Yahoo! Finance doing the same: https://finance.yahoo.com/quote/F/chart?p=F#eyJpbnRlcnZhbCI6IndlZWsiLCJwZXJpb2RpY2l0eSI6MSwidGltZVVuaXQiOm51bGwsImNhbmRsZVdpZHRoIjo0LjM0ODY1OTAwMzgzMTQxNzUsImZsaXBwZWQiOmZhbHNlLCJ2b2x1bWVVbmRlcmxheSI6dHJ1ZSwiYWRqIjp0cnVlLCJjcm9zc2hhaXIiOnRydWUsImNoYXJ0VHlwZSI6ImxpbmUiLCJleHRlbmRlZCI6ZmFsc2UsIm1hcmtldFNlc3Npb25zIjp7fSwiYWdncmVnYXRpb25UeXBlIjoib2hsYyIsImNoYXJ0U2NhbGUiOiJsaW5lYXIiLCJzdHVkaWVzIjp7IuKAjHZvbCB1bmRy4oCMIjp7InR5cGUiOiJ2b2wgdW5kciIsImlucHV0cyI6eyJpZCI6IuKAjHZvbCB1bmRy4oCMIiwiZGlzcGxheSI6IuKAjHZvbCB1bmRy4oCMIn0sIm91dHB1dHMiOnsiVXAgVm9sdW1lIjoiIzAwYjA2MSIsIkRvd24gVm9sdW1lIjoiI2ZmMzMzYSJ9LCJwYW5lbCI6ImNoYXJ0IiwicGFyYW1ldGVycyI6eyJ3aWR0aEZhY3RvciI6MC40NSwiY2hhcnROYW1lIjoiY2hhcnQifX19LCJwYW5lbHMiOnsiY2hhcnQiOnsicGVyY2VudCI6MSwiZGlzcGxheSI6IkYiLCJjaGFydE5hbWUiOiJjaGFydCIsImluZGV4IjowLCJ5QXhpcyI6eyJuYW1lIjoiY2hhcnQiLCJwb3NpdGlvbiI6bnVsbH0sInlheGlzTEhTIjpbXSwieWF4aXNSSFMiOlsiY2hhcnQiLCLigIx2b2wgdW5kcuKAjCJdfX0sInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fSwibGluZVdpZHRoIjoyLCJzdHJpcGVkQmFja2dyb3VuZCI6dHJ1ZSwiZXZlbnRzIjp0cnVlLCJjb2xvciI6IiMwMDgxZjIiLCJzdHJpcGVkQmFja2dyb3VkIjp0cnVlLCJldmVudE1hcCI6eyJjb3Jwb3JhdGUiOnsiZGl2cyI6dHJ1ZSwic3BsaXRzIjp0cnVlfSwic2lnRGV2Ijp7fX0sImN1c3RvbVJhbmdlIjpudWxsLCJzeW1ib2xzIjpbeyJzeW1ib2wiOiJGIiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IkYiLCJxdW90ZVR5cGUiOiJFUVVJVFkiLCJleGNoYW5nZVRpbWVab25lIjoiQW1lcmljYS9OZXdfWW9yayJ9LCJwZXJpb2RpY2l0eSI6MSwiaW50ZXJ2YWwiOiJ3ZWVrIiwidGltZVVuaXQiOm51bGwsInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fX1dfQ-- In both examples, the only custom parameter is setting the time window to 5 years.
- anshumankmr 4y ago> https://finance.yahoo.com/quote/F/chart?p=F#eyJpbnRlcnZhbCI6IndlZWsiLCJwZXJpb2RpY2l0eSI6MSwidGltZVVuaXQiOm51bGwsImNhbmRsZVdpZHRoIjo0LjM0ODY1OTAwMzgzMTQxNzUsImZsaXBwZWQiOmZhbHNlLCJ2b2x1bWVVbmRlcmxheSI6dHJ1ZSwiYWRqIjp0cnVlLCJjcm9zc2hhaXIiOnRydWUsImNoYXJ0VHlwZSI6ImxpbmUiLCJleHRlbmRlZCI6ZmFsc2UsIm1hcmtldFNlc3Npb25zIjp7fSwiYWdncmVnYXRpb25UeXBlIjoib2hsYyIsImNoYXJ0U2NhbGUiOiJsaW5lYXIiLCJzdHVkaWVzIjp7IuKAjHZvbCB1bmRy4oCMIjp7InR5cGUiOiJ2b2wgdW5kciIsImlucHV0cyI6eyJpZCI6IuKAjHZvbCB1bmRy4oCMIiwiZGlzcGxheSI6IuKAjHZvbCB1bmRy4oCMIn0sIm91dHB1dHMiOnsiVXAgVm9sdW1lIjoiIzAwYjA2MSIsIkRvd24gVm9sdW1lIjoiI2ZmMzMzYSJ9LCJwYW5lbCI6ImNoYXJ0IiwicGFyYW1ldGVycyI6eyJ3aWR0aEZhY3RvciI6MC40NSwiY2hhcnROYW1lIjoiY2hhcnQifX19LCJwYW5lbHMiOnsiY2hhcnQiOnsicGVyY2VudCI6MSwiZGlzcGxheSI6IkYiLCJjaGFydE5hbWUiOiJjaGFydCIsImluZGV4IjowLCJ5QXhpcyI6eyJuYW1lIjoiY2hhcnQiLCJwb3NpdGlvbiI6bnVsbH0sInlheGlzTEhTIjpbXSwieWF4aXNSSFMiOlsiY2hhcnQiLCLigIx2b2wgdW5kcuKAjCJdfX0sInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fSwibGluZVdpZHRoIjoyLCJzdHJpcGVkQmFja2dyb3VuZCI6dHJ1ZSwiZXZlbnRzIjp0cnVlLCJjb2xvciI6IiMwMDgxZjIiLCJzdHJpcGVkQmFja2dyb3VkIjp0cnVlLCJldmVudE1hcCI6eyJjb3Jwb3JhdGUiOnsiZGl2cyI6dHJ1ZSwic3BsaXRzIjp0cnVlfSwic2lnRGV2Ijp7fX0sImN1c3RvbVJhbmdlIjpudWxsLCJzeW1ib2xzIjpbeyJzeW1ib2wiOiJGIiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IkYiLCJxdW90ZVR5cGUiOiJFUVVJVFkiLCJleGNoYW5nZVRpbWVab25lIjoiQW1lcmljYS9OZXdfWW9yayJ9LCJwZXJpb2RpY2l0eSI6MSwiaW50ZXJ2YWwiOiJ3ZWVrIiwidGltZVVuaXQiOm51bGwsInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fX1dfQ-- https://finance.yahoo.com/quote/F/chart?p=F#eyJpbnRlcnZhbCI6... Dear god... this link was real. I thought it was like a joke or something
- barbazoo 4y ago> Another great benefit is that these urls can be embedded. That means the user can put their graph on any ewb page that supports embedding. I see people typically do this with wikis like Notion, which means you can share with a team This is so valuable that it can't be overstated. Being able to store the raw data in a link WITH the visual representation, you'll never struggle trying to find out who has the latest version.
- wildrhythms 4y agoBingo. I use this all the time to let users pass preconfigurations of internal tools back and forth. These are tools that live on the client and don't have a backend. The downside is my users complain about 'long/ugly links' which is another problem...
- zX41ZdbW 4y agoI'm successfully* using it in a few personal projects: ClickHouse Playground: https://play.clickhouse.com/play?user=play#U0VMRUNUIDE= https://play.clickhouse.com/play?user=play#U0VMRUNUIDE= ClickHouse Dashboards: https://sql.clickhouse.com/dashboard#eyJob3N0IjoiaHR0cHM6Ly9zcWwuY2xpY2tob3VzZS5jb20iLCJ1c2VyIjoicGxheSIsInF1ZXJpZXMiOlt7InRpdGxlIjoiQ2xpY2tIb3VzZSIsInF1ZXJ5IjoiU0VMRUNUIHRvTW9uZGF5KHRpbWUpOjpEYXRlVGltZTo6SU5ULCBzdW0oaGl0cykgRlJPTSB3aWtpc3RhdCBXSEVSRSBwYXRoID0gJ0NsaWNrSG91c2UnIEdST1VQIEJZIDEgT1JERVIgQlkgMSBGT1JNQVQgSlNPTkNvbXBhY3RDb2x1bW5zIn0seyJ0aXRsZSI6Ik15U1FMIiwicXVlcnkiOiJTRUxFQ1QgdG9Nb25kYXkodGltZSk6OkRhdGVUaW1lOjpJTlQsIHN1bShoaXRzKSBGUk9NIHdpa2lzdGF0IFdIRVJFIHBhdGggPSAnTXlTUUwnIEdST1VQIEJZIDEgT1JERVIgQlkgMSBGT1JNQVQgSlNPTkNvbXBhY3RDb2x1bW5zIn0seyJ0aXRsZSI6IlBvc3RncmVTUUwiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdQb3N0Z3JlU1FMJyBHUk9VUCBCWSAxIE9SREVSIEJZIDEgRk9STUFUIEpTT05Db21wYWN0Q29sdW1ucyJ9LHsidGl0bGUiOiJFbGFzdGljc2VhcmNoIiwicXVlcnkiOiJTRUxFQ1QgdG9Nb25kYXkodGltZSk6OkRhdGVUaW1lOjpJTlQsIHN1bShoaXRzKSBGUk9NIHdpa2lzdGF0IFdIRVJFIHBhdGggPSAnRWxhc3RpY3NlYXJjaCcgR1JPVVAgQlkgMSBPUkRFUiBCWSAxIEZPUk1BVCBKU09OQ29tcGFjdENvbHVtbnMifSx7InRpdGxlIjoiUmVkaXMiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdSZWRpcycgR1JPVVAgQlkgMSBPUkRFUiBCWSAxIEZPUk1BVCBKU09OQ29tcGFjdENvbHVtbnMifSx7InRpdGxlIjoiQmlnUXVlcnkiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdCaWdRdWVyeScgR1JPVVAgQlkgMSBPUkRFUiBCWSAxIEZPUk1BVCBKU09OQ29tcGFjdENvbHVtbnMifSx7InRpdGxlIjoiSGFkb29wIiwicXVlcnkiOiJTRUxFQ1QgdG9Nb25kYXkodGltZSk6OkRhdGVUaW1lOjpJTlQsIHN1bShoaXRzKSBGUk9NIHdpa2lzdGF0IFdIRVJFIHBhdGggPSAnQXBhY2hlX0hhZG9vcCcgR1JPVVAgQlkgMSBPUkRFUiBCWSAxIEZPUk1BVCBKU09OQ29tcGFjdENvbHVtbnMifSx7InRpdGxlIjoiU3BhcmsiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdBcGFjaGVfU3BhcmsnIEdST1VQIEJZIDEgT1JERVIgQlkgMSBGT1JNQVQgSlNPTkNvbXBhY3RDb2x1bW5zIn0seyJ0aXRsZSI6IlNRTCIsInF1ZXJ5IjoiU0VMRUNUIHRvTW9uZGF5KHRpbWUpOjpEYXRlVGltZTo6SU5ULCBzdW0oaGl0cykgRlJPTSB3aWtpc3RhdCBXSEVSRSBwYXRoID0gJ1NRTCcgR1JPVVAgQlkgMSBPUkRFUiBCWSAxIEZPUk1BVCBKU09OQ29tcGFjdENvbHVtbnMifSx7InRpdGxlIjoiT3JhY2xlIiwicXVlcnkiOiJTRUxFQ1QgdG9Nb25kYXkodGltZSk6OkRhdGVUaW1lOjpJTlQsIHN1bShoaXRzKSBGUk9NIHdpa2lzdGF0IFdIRVJFIHBhdGggPSAnT3JhY2xlX0RhdGFiYXNlJyBHUk9VUCBCWSAxIE9SREVSIEJZIDEgRk9STUFUIEpTT05Db21wYWN0Q29sdW1ucyJ9LHsidGl0bGUiOiJEdWNrREIiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdEdWNrREInIEdST1VQIEJZIDEgT1JERVIgQlkgMSBGT1JNQVQgSlNPTkNvbXBhY3RDb2x1bW5zIn0seyJ0aXRsZSI6IlNpbmdsZVN0b3JlIiwicXVlcnkiOiJTRUxFQ1QgdG9Nb25kYXkodGltZSk6OkRhdGVUaW1lOjpJTlQsIHN1bShoaXRzKSBGUk9NIHdpa2lzdGF0IFdIRVJFIHBhdGggSU4gKCdNZW1TUUwnLCAnU2luZ2xlU3RvcmUnKSBHUk9VUCBCWSAxIE9SREVSIEJZIDEgRk9STUFUIEpTT05Db21wYWN0Q29sdW1ucyJ9LHsidGl0bGUiOiJCaWcgRGF0YSIsInF1ZXJ5IjoiU0VMRUNUIHRvTW9uZGF5KHRpbWUpOjpEYXRlVGltZTo6SU5ULCBzdW0oaGl0cykgRlJPTSB3aWtpc3RhdCBXSEVSRSBwYXRoID0gJ0JpZ19EYXRhJyBHUk9VUCBCWSAxIE9SREVSIEJZIDEgRk9STUFUIEpTT05Db21wYWN0Q29sdW1ucyJ9LHsidGl0bGUiOiJHcmVlbnBsdW0iLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdHcmVlbnBsdW0nIEdST1VQIEJZIDEgT1JERVIgQlkgMSBGT1JNQVQgSlNPTkNvbXBhY3RDb2x1bW5zIn0seyJ0aXRsZSI6IlRpREIiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgc3VtKGhpdHMpIEZST00gd2lraXN0YXQgV0hFUkUgcGF0aCA9ICdUaURCJyBHUk9VUCBCWSAxIE9SREVSIEJZIDEgRk9STUFUIEpTT05Db21wYWN0Q29sdW1ucyJ9LHsidGl0bGUiOiJTbm93Zmxha2UiLCJxdWVyeSI6IlNFTEVDVCB0b01vbmRheSh0aW1lKTo6RGF0ZVRpbWU6OklOVCwgbGVhc3QoMjAwMDAsIHN1bShoaXRzKSkgRlJPTSB3aWtpc3RhdCBXSEVSRSBwYXRoID0gJ1Nub3dmbGFrZV9JbmMuJyBHUk9VUCBCWSAxIE9SREVSIEJZIDEgRk9STUFUIEpTT05Db21wYWN0Q29sdW1ucyJ9XSwicGFyYW1zIjp7fX0= https://sql.clickhouse.com/dashboard#eyJob3N0IjoiaHR0cHM6Ly9... The second example shows you why it is not an entirely good idea. The second link cannot be posted in Slack and Google Meet, so I have to use an URL shortener... Luckily I have it in my disposal: https://pastila.nl/ https://pastila.nl/ Example: https://pastila.nl/?02a0d469/8f49f7e4406bd4fbc0e7b142c470dfb0.link https://pastila.nl/?02a0d469/8f49f7e4406bd4fbc0e7b142c470dfb...
- dang 4y agoRelated ongoing thread: Show HN: URL Snake - https://news.ycombinator.com/item?id=34288577 https://news.ycombinator.com/item?id=34288577 - Jan 2023 (30 comments)
- oaiey 4y agoJust do not. That or alternatively a hidden field is how asp.net WebForms did it state management 20 years ago. Worst possible idea ever. Good for small scale unimportant external state management but not for your everyday web app.
- tomwheeler 4y agoIt also degraded performance. I had to use a .NET-based issue tracking web app 20 years ago. The performance was horrible, with pages sometimes taking 20 seconds to load. I eventually viewed the source of the page and discovered a form field called "viewstate" that contained several megabytes of encoded data.
- jonathanoliver 4y agoWhen I saw this idea all I could think of was the ASP.NET "postback" form data and URL data! I'm glad to not have to deal with that anymore.
- withinrafael 4y agoI don't have an opinion on this but do want to mention that LastPass does not (currently) encrypt the URL portion of its entries in the secure vault. Something to keep in mind!
- brundolf 4y agoSomething to be careful about here is that browsers/proxies/etc have arbitrary length limits on URLs, and they can vary by quite a lot We did this once with a web-based REPL, where you could click a button to copy a link to something you'd previously eval'd and then send that to someone else and their buffer would be preloaded with it. It was super nifty, until someone tried it with a buffer that was a few hundred lines long and at least one browser just said "nope". It sounds like OP is doing some smart stuff to minimize URL length, which should help, but there's still a limit somewhere
- 2342346666 4y ago[dead]
- jonnycomputer 4y agoWhy not use localStorage or sessionStorage instead of the URL?
- escot 4y agoURLs are great because you can share them. I may also add support for local storage, but it won't remove the ability to share via URL.
- temporallobe 4y agoI prefer this as well, but it’s not as portable.
- phkahler 4y agoI did this for an Othello game back in the 90's. The state was encoded in the URL along with the players move. It seemed weird to encode a slightly different URL for every move the player might click, but that also meant squares that were not legal moves didn't get a URL. And that meant the mouse pointer would change when you hovered over a valid square! Another trick was to return the updated board state, but also include an automatic reload after a few seconds with the computers next move already determined. This made it look like "thinking" was going on when in fact it was already decided when the board updated on players move ;-) This was all in a CGI script. As others have pointed out, it also supported "undo" via the back button. Fun.
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- paxys 4y agoBase 64 is probably not the best encoding for this, since the URL allows for a wider range of characters. You can be more efficient by using them as well.
- macspoofing 4y agoBase 64 is fine - he just needs to url-encode the parameter.
- manchmalscott 4y agoI am pretty certain BeepBox (An online sequencer/tracker) does this as well. It's pretty neat to send something in progress to a friend with just a URL, no accounts needed.
- cwt137 4y agoA few years ago, I worked on an app where some of the state was kept in the session and some was on the url as GET params. We ran into an issue where some browsers would only accept urls that were less than 1024 chars long. Is that still an issue today?
- tomtomistaken 4y agoWe are testing this on a map[0], it's fun. When tweeting the link, the tweet and its state is added to the map. Also, map stories are possible through Twitter threads. We just implemented a draw function and are working on an implementation for external geojsons. [0] https://map.decarbnow.space https://map.decarbnow.space
- berelig 4y agoThis is exactly how Shel Kaphan (first eng @ Amazon) handled the state of a shopping cart in the mid 90s. Here is him discussing some of the pitfalls: https://lists.w3.org/Archives/Public/www-talk/1995NovDec/0202 https://lists.w3.org/Archives/Public/www-talk/1995NovDec/020...
- jncraton 4y agoI did something similar in a simple whiteboarding app that I made a while back: https://github.com/jncraton/box-line-text https://github.com/jncraton/box-line-text The data representation could probably improve in terms of readability, but I'm happy with the way it provides a concise encoding while still including the text from the document directly: https://box-line-text.netlify.app/#;c2121Hello;5321;c1341Hacker+News https://box-line-text.netlify.app/#;c2121Hello;5321;c1341Hac...!
- jdlyga 4y agoYou've just invented video game passwords! This reminds me of transferring over my save data from Golden Sun to Golden Sun: The Lost Age by typing in a 260 character password.
- jcuenod 4y agoThis is a useful idea when you've got complex nested state. The problem is changing any particular part of the state is non-trivial. I ended up making `friendly-serializer`[0] to "make objects more accessible in urls." The idea is that instead of a base64 string, you get something that is much easier to edit in the url bar: > name=John%20Doe&age=42&address.street=123%20Main%20Street&address.city=Anytown&address.state=CA&address.phoneNumbers.0=123-456-7890&address.phoneNumbers.1=234-567-8901 There's a similar npm project to [0] that I discovered after I'd published this, but I don't recall the name. PRs welcome. [0] https://www.npmjs.com/package/friendly-serializer https://www.npmjs.com/package/friendly-serializer
- frosted-flakes 4y agoYou can have multiple values under the same search parameter. For example, ?a=b&a=c&a=d, which would be the array [b, c, d]. Including the index key seems redundant. The native URLSearchParams browser interface even supports this with the getAll method. https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/getAll https://developer.mozilla.org/en-US/docs/Web/API/URLSearchPa...
- jcuenod 4y agoGreat point! Added to my TODOs
- jcuenod 4y agoI found the other package: https://www.npmjs.com/package/friendly-querystring https://www.npmjs.com/package/friendly-querystring (noting mostly for my own sake)
- saghm 4y agoI imagine I'm not the first one to think of this, but a little while back I wrote a toy pastebin-like webpage that stored the code being rendered directly in the URL (with base64 and gzip compression to make it a bit smaller, although it still was quite large by usual standards). My thinking was that rather than having a centralized app for this publicly available, making a small page that could be statically hosted would make it easy for people or organizations to host their own page with whatever security they need (e.g. behind a firewall or VPN) and then the links could be shared privately on Slack or whatever without a need to add functionality for determining who should have access or how long to keep the code snippet around and instead just piggyback off of the privacy of whatever channel/DM they sent it across and how long the Slack instance is configured to retain history. When I first came up with this idea, I was going to write some sort of server backend rather than just doing everything in the frontend, but once I started actually working on it, I realized that it wouldn't really add any value and it would make it a bit more annoying for people to self-host. Since then, I've wondered a bit how viable "static pages with state in the URL that can be easily self-hosted" would be as an alternative to a desktop GUI or Electron app for more technical users. One of the nicest parts of this approach to me is that I was able to make in only a few hours one evening despite knowing only the basics of webdev from maybe 8-10 years ago and next to nothing about programming GUIs in general. This makes me think that it wouldn't be too hard for people to fork and modify it to their own liking (e.g. changing the hard-coded style settings for rendering the code snippets), so there could be potential for an ecosystem to grow organically around something like this. In case anyone is curious to take a look: https://gitlab.com/saghm/pastml/ https://gitlab.com/saghm/pastml/
- Ndymium 4y agoGreat minds think alike? I just posted about my URL-using pastebin: https://news.ycombinator.com/item?id=34315577 https://news.ycombinator.com/item?id=34315577
- dzaima 4y agoThere are quite a few of these apparently. https://topaz.github.io/paste/ https://topaz.github.io/paste/ (lzma) from the creator of Advent Of Code, and mine: https://dzaima.github.io/paste/ https://dzaima.github.io/paste/ (pako)
- Ndymium 4y agoLast November I had covid and during that time I wrote a little pastebin that runs in the browser, compresses the paste data with Brotli, and puts it in the URL. It has line numbers, file naming, and syntax highlighting so it's feature complete for my own use. Here's a demo, but beware, the URLs are loooong: https://nicd.gitlab.io/t/#NhfW?Qm3F?6-&22c&CQZXuP+Aej5OXzXk7WPSpyN1MjAdr+PwAZltsgU&3R8c8cCSUJBybp+~U7~IOktUPAS/rXc+60kTVsWT21IwCw$r2o+Em3N5zyYc?qhE7ECJWHoSjQ8NemN8BZk_2UQ~Nf-gUr4Y/j854zD4RK=/QKB$qJy&uNSzZiGpk3dCj0alu?CaHH9Uaqpk9kh~1so0DqHLIdmIYJ8C2gpA625pD-VDal-rkL/egUCa/P$2f5kdOdgipOVc?ikrRv8bT5$ADVQR7PRt$kS4TpNO9&P74.xsv-ZsZVEHW6dTExkj8u1Pr3JZ=HJ7+bIx8aS6ounfMpRg=fUHqG5PYiLD9FVChk7aIb0nCMmL8K3A4VPuUDwWlO~zAta8YyiU8SGjromJ~I.edi9WoVMbp-lt1j.kydxkvLyYYRmM?N0bqbjL8P39cL~HUyi_+RW6~dsNW4c9n.sYlNN7h=aUs4jT+Mi_&EtTDdlA9Qtbj_Ln1jxFGS.OsSuHYNubts_eGJ_x https://nicd.gitlab.io/t/#NhfW?Qm3F?6-&22c&CQZXuP+Aej5OXzXk7... I find it interesting to sometimes play around with the pasted data just to see how it compresses. Sometimes adding a character or two may cut several characters from the URL length!
- didericis 4y agoCompression is one of the closest things to real life magic I’m aware of. Especially now that people have basically compressed the entire internet into a couple gig AI models. And then when I think about biology/genetics and what kind of unfathomably weird and convoluted compression is going on there, and then think about whatever it is our brain is doing… and then when I think about how like all of our perception is probably some kind of weird inescapable compressed representation of true reality… It’s all magic. Real life magic.
- jansan 4y agoIs the Brotli compression done in the browser? If so, can you give some insight how this is done?
- Ndymium 4y agoYep, it is! You can find the sources on GitLab[0]. The compression is done using brotli-wasm[1]. The entry point to the compression is the syncCompress[2] function, which converts the data to UTF-8, adds the needed header bytes, and then compresses using brotli-wasm. Decompression is done in a streaming way in streamDecompress[3]. This is to avoid zip bomb attacks, where even a short URL could decompress to gigabytes of data, locking the browser. Thankfully brotli-wasm had streaming decompression builtin, I just had to write the wrapper code to update the text content and the status bar in the UI. You can find the brotli-wasm code I'm using in the vendor folder[4], there is a JS wrapper and then the WASM code (both are straight from brotli-wasm). [0] https://gitlab.com/Nicd/t https://gitlab.com/Nicd/t [1] https://github.com/httptoolkit/brotli-wasm https://github.com/httptoolkit/brotli-wasm [2] https://gitlab.com/Nicd/t/-/blob/05e587b0183ff80b1c6e050b5d30f375330572ec/tahnaroskakori.js#L196 https://gitlab.com/Nicd/t/-/blob/05e587b0183ff80b1c6e050b5d3... [3] https://gitlab.com/Nicd/t/-/blob/05e587b0183ff80b1c6e050b5d30f375330572ec/tahnaroskakori.js#L223 https://gitlab.com/Nicd/t/-/blob/05e587b0183ff80b1c6e050b5d3... [4] https://gitlab.com/Nicd/t/-/tree/05e587b0183ff80b1c6e050b5d30f375330572ec/vendor https://gitlab.com/Nicd/t/-/tree/05e587b0183ff80b1c6e050b5d3...
- jwoglom 4y agoLike some other commenters mentioned, this is a cool idea, however by storing JSON data inside base64, the length of the URL blows up very quickly as you start storing more state. While technically URLs have no formal length limit, various sources suggest that URLs with more than around 2,048 characters start causing issues in browsers, and around 8,196 start causing issues in CDNs (https://stackoverflow.com/a/417184 https://stackoverflow.com/a/417184). You can work around this partially by not storing this state information in the query string (path/to?<state>) and instead using a hash string (path/to#<state>), and then extract that data in JavaScript such that it's not sent to the server at all. IMO, the canonical way to solve this problem is using protocol buffers, which you can then serialize into a much smaller number of bytes, which is then base64 encoded. For example, as mentioned in another comment in this thread (https://news.ycombinator.com/item?id=34314578 https://news.ycombinator.com/item?id=34314578), Yahoo Finance has a 1,616 character-long URL with 1,572 characters of base64-encoded JSON state: > {"interval":"week","periodicity":1,"timeUnit":null,"candleWidth":4.3486590038314175,"flipped":false,"volumeUnderlay":true,"adj":true,"crosshair":true,"chartType":"line","extended":false,"marketSessions":{},"aggregationType":"ohlc","chartScale":"linear","studies":{" vol undr ":{"type":"vol undr","inputs":{"id":" vol undr ","display":" vol undr "},"outputs":{"Up Volume":"#00b061","Down Volume":"#ff333a"},"panel":"chart","parameters":{"widthFactor":0.45,"chartName":"chart"}}},"panels":{"chart":{"percent":1,"display":"F","chartName":"chart","index":0,"yAxis":{"name":"chart","position":null},"yaxisLHS":[],"yaxisRHS":["chart"," vol undr "]}},"setSpan":{"multiplier":5,"base":"year","periodicity":{"period":1,"interval":"week"}},"lineWidth":2,"stripedBackground":true,"events":true,"color":"#0081f2","stripedBackgroud":true,"eventMap":{"corporate":{"divs":true,"splits":true},"sigDev":{}},"customRange":null,"symbols":[{"symbol":"F","symbolObject":{"symbol":"F","quoteType":"EQUITY","exchangeTimeZone":"America/New_York"},"periodicity":1,"interval":"week","timeUnit":null,"setSpan":{"multiplier":5,"base":"year","periodicity":{"period":1,"interval":"week"}}}]} The un-base64'd JSON dictionary is 1,162 characters long, 569 of which is composed of just the key names (48 percent!), and most of the remaining fields likely contain their default value. If this was instead encoded in protobuf, the key names wouldn't need to be included, since fields are referenced by their field ID, and default field values would take up little-to-no space since when the default value is present it isn't encoded into the structure. I presume that, if done efficiently, you could likely make an equivalent representation in protobuf that is 1/4th or even 1/8th the size. You also get, for better or for worse, what is essentially obfuscation for free (yes, you can read out the packed format, but without an equivalent protobuf struct definition it's still hard to tell what field is which, and the entire operation becomes much more labor-intensive).
- dools 4y agoI’ve been using this hosted on my own server since it was first posted in 2013: https://news.ycombinator.com/item?id=5696127 https://news.ycombinator.com/item?id=5696127
- martini333 4y agoVuejs Playground does this. This is the url for the default tamplate: https://sfc.vuejs.org/#eNo9j71uwzAMhF+F5eIWqCV0NZQA3foGXbikjpw40B9EOR0EvXspp8imu9N9OFb8TEndN4sTGp7zmgqwLVs6Ulh9irlAhWwXaLDk6GGQrwMFCnMMXMDzBQ49fx2+rHMRvmN255fhjYLRD5yARBTrkzsVKwrAXD+Ote7l1owWtbtrSFuB++jj2boDoeSEEhn9bOM7PlaN/pTUjWOQ3bW36T9gwgl2p3uytmvCaymJJ615mfu1N1YxX7S8VN5CWb1Vlv34k+Mv2yxgwo5oFBq2P3/sZE8= https://sfc.vuejs.org/#eNo9j71uwzAMhF+F5eIWqCV0NZQA3foGXbikj...
- holdenk 4y agoI did something similar using Racket's (nee PLT scheme) web programming module ( https://www2.ccs.neu.edu/racket/pubs/hosc07-sk-mf.pdf https://www2.ccs.neu.edu/racket/pubs/hosc07-sk-mf.pdf ) back with an app that got on slashdot -- https://github.com/holdenk/web2.0collage https://github.com/holdenk/web2.0collage The theory was wonderful (yay! stateless load balancer etc.) but in practice browsers at the time were less than happy with trying to store that much state in the URL.
- threeseed 4y agoThis technique goes back to the late 90s where Apple WebObjects (owned by NeXT at the time) pioneered this approach in their web framework. https://en.wikipedia.org/wiki/WebObjects https://en.wikipedia.org/wiki/WebObjects Was quite revolutionary at the time and it also included the first (or one of the very earliest at least) SQL ORMs.
- numair 4y agoYou’re the first and only person to point out this fact, which shows how depressingly little history is studied by people who work in this field. It’s a shame it’s become about getting to The Money as quickly as possible…
- firstbabylonian 4y agoHow do we go about passing this kind of historic knowledge between generations of engineers? In my observation, most newcomers to the industry are trained either academically or through self-guided practical learning, i.e. by hacking and reading tutorials. Neither method exposes them to such 'contemporary history' of innovation within the field.
- wildrhythms 4y agoI got a Compsci degree and we did in fact learn some history, figures like Grace Hopper and Alan Turing, how punched card computers worked (we even got to make our own punched cards!) Obviously people who are passionate about computers will find such history very interesting; the newcomers with dollar signs in their eyes won't care, they just want to 'make an app'.
- zelphirkalt 4y agoRacket does this in its web framework and docs.
- aplummer 4y agoI do like the approach and when it works great thats fantastic - please be careful of this as an attack vector. I know of at least one bank where this was exploited, because people see the base url, assume safe, and can't read the embedded escape / javascript in the longer part. Especially when the link is zipped into a little clickable thing and you can't see the URL at all.
- builwithlogic 4y agoThis is fine for f its public information and if thats fine then why not just add a param with a url encoded json string. Would this make the url shorter or longer? I think shorter. So why base64encode? Just wondering never created an entire app around this idea
- escot 4y agoThe encoding gives you cleaner urls that are restricted to the characters that base64 outputs, not necessarily shorter. The compression is to make it shorter.
- ceritium 4y agoI did the same for https://markdowntable.jose.gr https://markdowntable.jose.gr As some comments suggest, I will move the data from the query string to the URI fragment to avoid the length limitation.
- binarymax 4y agoShameless plug for bashfill - a fun little drawing program for making art for bash stdout: https://max.io/bash.html?zip=eDE1eTF4MjRlMXgzeTF4MzB5MXg1ZTF4NDBlMXg0eTJ4NXc1eDd5MXg3eTF4NncyZTF4M3kyeDRtMXc3eDE5bTF3M2UxdzJ4MXkyeDE1eTF4MTllMXc0eTJ4MnkxeDI2eTF4NGUxeDR5NHgxM3c1eDE0ZTF4MTltMXc3eDEzZTF4NDBlMXg0MGUxeDdiMWMydzF4N2IxYzJ3MXgxOGUxYjF4MWIxeDFiMXgxYjFjMm0xeDNiMXgxYjF4MWIxYzJtMXgyYjF4MWIxeDFiMXgxYjF4MWIxeDFiMXgxYjF4MWIxeDFiMWUxZzFjOW0zZzFjM2cxYzNtNGcxYzRtMWIxbTFiMWcxYzNiMW0xZTFtM2M0YjFtMWIxYzhtMmcxYzViMW0xYjFnMWM0YjFtMWIxbTFnMWMxZTFjMmIxbTFiMW0xYjFtMWcxYzViMW0xYjFnMWMzbTFiMW0xYjFnMWMzYjFtMWIxbTFiMWcxYzNtMWIxZTFtMmcxYzdiMW0xYjFtMWM0bTFjMWcxYzVtMWIxZzFjMTFlMWMzYjFtMWIxbTFiMW0xYjFnMWMzYjFtMWIxbTFjMTJiMm0xYjFtMWcxYzNtMWUxYzExbTFiMWM1YjF3NWMyYjFtMWIxYzN3M2IxbTFiMW0xYzFlMWMzdzJiMWM5YjJ3Mm01YjFjM3c0bTJ3MWIxYzRlMWMydzFtMncxYjl3Mm0yeTR3MW0xYjFjMXcxbTNjMXcxYzFtMXcxYjRlMXcybTF5M3cxMG0xeTh3Mm0xYzF5MWMxeTFjMXkydzVlMXk0MA== https://max.io/bash.html?zip=eDE1eTF4MjRlMXgzeTF4MzB5MXg1ZTF... ...made in 2013 :) Here's the js that runs it: https://max.io/bash.js https://max.io/bash.js
- temporallobe 4y agoOut of necessity for a very similar issue, I actually wrote a small Javascript utility for this that does all this automatically and uses optional symmetric encryption. Would it be against the rules to post it here?
- breck 4y agoThis is the way. Except I would never encode the data—just store state in plain text. That way you can edit urls by hand in a pinch (comes up a lot, actually). And more trustworthy and you can be sure you take your data with you. I do this in all my apps. https://ohayo.computer/ https://ohayo.computer/, https://simoji.pub/ https://simoji.pub/, https://try.scroll.pub/ https://try.scroll.pub/, https://jtree.treenotation.org/designer/ https://jtree.treenotation.org/designer/ etc. At one point I also made a tiny lib to make it easier: https://breckyunits.com/patch/ https://breckyunits.com/patch/
- gautamdivgi 4y agoWeb servers and http enabled services can limit the length of headers and url. While this can be done it runs the risk of having surprises when unknown limits are encountered. Most of these limits are buried deep in docs, not easily visible.
- jerryzh 4y agoone problem to me is that I run a script remove parameter in url(for tracker) ofc I can set a whitelist but it is a issue i consider
- amadeuspagel 4y agoHow much of a concern is the length of the URL? It doesn't matter for bookmarks, but what about sharing? Character limits, or even just the unwieldiness of long URLs in a textarea?
- stevebmark 4y agoThe Typescript Playground (https://www.typescriptlang.org/play https://www.typescriptlang.org/play) does something similar, it gzips the contents of your code and puts it in the URL. Pretty sweet!
- shepherdjerred 4y agoShinylive, which lets you create and share data science apps, takes this approach: https://shiny.rstudio.com/py/docs/shinylive.html https://shiny.rstudio.com/py/docs/shinylive.html
- 867-5309 4y agoI'm just getting a 414 Error
- MutableLambda 4y agoBut it was done already in widely known in narrow circles PlantUML years ago?
- debacle 4y agoCongratulations, you've implemented ViewState from aspx.
- 12311231231 4y agoIn other words, tracking
- vesinisa 4y agoThis is all fun and games until the junior dev edits the code to store the user's search history in that obfuscated appState object. The users end up sharing their URLs in public and unknowingly leaking some very private data.
- moritzwarhier 4y agoGreat for complex apps in the browser and sharing complex save states! Bad for ordinary, mundane web applications and sharable URLs! Like, great for a musical step sequencer in the browser, bad for a website or HTTP service OTOH, app state on websites of commercial service prodivders might be best represented by a JSON blob anyway. In something like a checkout process or form submit, of course this doesn't matter much. But I prefer human-readable URLs wherever possible. And I implemented a similar pattern once, too. It's a very interesting approach in intself. Relevant POJO state tends to be small enough but long lists or resourcrs in a URL are not supported by most servers and not advisable.
- metahost 4y agoThere is a max length to URLs after which it is all wild west based on the browser implementation. See: https://stackoverflow.com/a/417184 https://stackoverflow.com/a/417184
- jwilliams 4y agoNot necessarily mandatory - but I'd also recommend a stable sort on the keys prior to `stringify`.
- anigbrowl 4y agoIt's clever, but I hate it: it makes computing weird and inaccessible to non-technical people, and makes citations etc. needlessly difficult to manage.
- actinium226 4y agoThis is really cool, both the state-in-url and the app itself. Just wondering, how long did it take you to put the app together?
- escot 4y agoI've been working on the app for over a year. The state-in-url thing was a pretty small portion of time, although I've fixed/updated it several times in that year to make it better. Thanks for the feedback. Did you make a flowchart?
- pdntspa 4y agoThe early 2000's called, they want their ASP pages and IIS license back
- zengid 4y agorelevant to mention the new tan-stack router that does this: https://tanstack.com/router/v1 https://tanstack.com/router/v1
- bmalicoat 4y agoI love stuff like this. Around 2008 or so I was working on a Java game for the T-Mobile Sidekick (aka hiptop). The platform let you register url scheme handlers so I registered "drod" (the game was a from-scratch port of Deadly Rooms of Death, a classic shareware game). Since the game was a 16x16 grid-based game with 3 layers, it was super efficient at expressing levels, including monsters and locks and keys, with just a limited number of bits. On my website I had "DLC" in the form of drod://[base64 encoded level here]. It always filled me with joy that users already downloaded the levels when they navigated to the website. Clicking the link just opened the game with the data they already had on their device.
- kissgyorgy 4y agoI did something similar, but compressed with pako to make the URL as short as possible: https://www.pokerregion.com/?r=Y2RwYBBgYGFkcGAQYGBhZHBgEGBgYQQA https://www.pokerregion.com/?r=Y2RwYBBgYGFkcGAQYGBhZHBgEGBgY... Here is the compression code: https://gist.github.com/kissgyorgy/39623a7d0ba2f6faafb464b72a1d412d https://gist.github.com/kissgyorgy/39623a7d0ba2f6faafb464b72... I used the properties of my data structure (multiple cards represented in a byte as bits) to represent the same data on less bytes (to avoid compressing JSON with unnecessary characters)
- nojvek 4y agoShameless plug: I made a library to encode any json as query/hash params in a human readable manner adhering to url friendly characters. https://github.com/recurrency/urltron https://github.com/recurrency/urltron Perfect use case for storing page state in url.
- vqt123 4y agoi do this on a site i threw together to annotate youtube videos with timestamps https://youtubenotes.com/ https://youtubenotes.com/ i used sveltekit and vercel
- schwartzworld 4y agoI built a tic tac toe game for my daughter a while a go that stores the game state in the URL as a proof of a similar concept. https://letter-press.netlify.app/ttt/ https://letter-press.netlify.app/ttt/
- splistud 4y ago[dead]
- deleted 4y ago[deleted]
- anon223345 4y agoI saw a $12 million app have to be essentially rewritten (at a bank) The “genius dev lead who went to Princeton” kept pushing that they went to Princeton so people stopped arguing against it Tried to do this securely and got pwned in the very first demo
- winrid 4y agoI mean, they got pwned because they didn't validate the state against the current user's session. Not because storing state in the URL is insecure.
- didericis 4y agoIf you’re validating client url state against server session state that kind of defeats the purpose of trying to put all the state in the url. You’re technically correct/sounds like you agree it’s still a bad idea, even if there’s a way to duplicate certain state for validation and make it work. Staying shackled to the earth via stupid rules of thumb like minimizing client state in banking apps does keep you from flying straight into the sun, though, which is nice.
- forgotusername6 4y agoHow can you secure state stored in the URL?
- winrid 4y agoYou don't. You secure the resources the state accesses.
- Maksadbek 4y agoWorth to note that it actually should use the base62 https://en.wikipedia.org/wiki/Base62 https://en.wikipedia.org/wiki/Base62 It’s the same as base64 but w/o "+" and "?" symbols.
- bytesandbots 4y agoThere is a URL safe version of base64 that uses - and _ instead. Base64 tools can be more readily available.
- paulirish 4y agoHere's the non-psuedo code equivalent that can leverage the CompressionStream API rather than using a browserified-gzip-library (eg pako): https://github.com/GoogleChrome/lighthouse/blob/437eb4d757c52cd19994ccf80e91e872cf2f62c7/report/renderer/text-encoding.js#L18-L53 https://github.com/GoogleChrome/lighthouse/blob/437eb4d757c5... We use it in Lighthouse for the exact same purpose, a URL #hash full of state. We found that modern browsers support 10mb of data in the hash. https://github.com/GoogleChrome/lighthouse/pull/12509#discussion_r634842711 https://github.com/GoogleChrome/lighthouse/pull/12509#discus...
- ananthakumaran 4y agoAbout 6 years ago I had to do this on a project. We had charts with a lot of options and we wanted them to be bookmarkable and shared between colleagues. We started with base64, soon moved to a custom encoding with version support https://github.com/ananthakumaran/u https://github.com/ananthakumaran/u
- elsherbini 4y agoI learned about your library because the harmopark.app site uses and credits it. I plan to use it in a music app I'm developing. I saw someone forked it and removed the lodash dependency / minor refactoring https://github.com/ananthakumaran/u/compare/master...j-te:u:master https://github.com/ananthakumaran/u/compare/master...j-te:u:...
- quickthrower2 4y agoSince it is ephemeral, local storage is probably fine? Feels like a better solution.
- philwelch 4y agoAnother way to generate potentially shorter base64 strings is to use something like Python's `struct` to store packed binary data, and then base64 encode that. Better yet, if that data payload can be generated server-side, you can also sign that data payload, which allows you to statelessly verify the data payload itself. (cf. https://docs.python.org/3/library/struct.html https://docs.python.org/3/library/struct.html)
- deleted 4y ago[deleted]
- noduerme 4y agoI'm sorta debating the merits of various methods like this because there's something I want to "Show HN" which involves browser-based analysis of CSV files... but the way I built it for myself, I just run it on a Node server that parses the file once and stores it as json and serves it when you reopen a project. So now I want to bundle the CSV/json with then project file. But putting it all in a base64 url seems a little crazy when saving/retrieving gzip files from the local filesystem is just as good an option. I think this is interesting as something to consider for shared projects, but probably not ideal if the main goal is to have everything run locally anyway.
- dietmtnview 4y agoplease don't do this, especially if you work with map coordinates.
- a-dub 4y agodoing something like this means you have to pay attention to a few things: * back/forward button behavior * cache behavior * bookmarks over time surprising there's no discussion of it.
- redbar0n 4y ago> Since I update it on every graph edit, I get something major for free -- undo/redo. The browser's history stack becomes my undo/redo functionality. A pet peeve of mine is that webapps shouldn’t hijack the browsers default functionality, here being back/forward that should refer to pages, not mutations of the same page. Ideally, one would have a separate undo/redo button on the page for page or url mutations (which should always be in sync). But mutating the URL shouldn’t be done by pushing to the browser history stack, or if pushing one ought to remember to pop the current entry first so the result is a single mutated page on the history stack.
- deleted 4y ago[deleted]
- ohyash 4y agoI love this. My website tenor.cards has been backend-free for a while thanks to the URLs. https://tenor.cards/design_card/?p=Rm9yJTIwdGV4dCUyMHRoYXQlMjBpcyUyMGElMjBsZW5ndGglMjBvZiUyMGElMjB0d2VldCUyQyUyMGRvJTIweW91JTIwZXZlbiUyMG5lZWQlMjB0byUyMHN0b3JlJTIwaXQlMjBpbiUyMGElMjBkYXRhYmFzZSUzRiUyMCVGMCU5RiVBNiVCOQ==&ct=skew https://tenor.cards/design_card/?p=Rm9yJTIwdGV4dCUyMHRoYXQlM... I didn't even know about window location hash, which I just learned from the other comments. Thank y'all.
- instagary 4y agoThis reminded me of Xstate (https://xstate.js.org/docs/ https://xstate.js.org/docs/). Their visual editor in VSCode does this.
- twhitmore 4y agoLimited in size as URLs encounter size limits: https://stackoverflow.com/a/417184/768795 https://stackoverflow.com/a/417184/768795 I wouldn't consider state in the URL fully general, as data can easily exceed that for many apps; but it's a useable technique where it fits. Meaningful individual parameters are preferable, but similar size limits apply either way.
- dzhiurgis 4y agoIIRC some base64 characters need to go thru urlEncode https://stackoverflow.com/questions/1374753/passing-base64-encoded-strings-in-url https://stackoverflow.com/questions/1374753/passing-base64-e...
- NoobNoob 4y agoI too obsess over shorter URLs but I do love the idea that the whole state is just a URL. From the comments, use good enough defaults and URL shorteners where necessary, and it's a brilliant design for a free-tier application.
- ngc6677 4y agoAlso this: https://goog.space/?data=eyJ0eXBlIjoidGV4dCIsInZhbHVlIjoiIyBoZWxsbyBITlxuXG5XZWxjb21lIHRvIFtnb29nLnNwYWNlXShodHRwczovL2dvb2cuc3BhY2UpXG5cbi0gZG9lcyBpdCB3b3JrIGZvciB5b3U%2FXG4tIGhvdyBkbyB5byBkbz9cblxuPHN0eWxlPlxubGkge1xuICBsaXN0LXN0eWxlOiBzcXVhcmU7XG4gIGNvbG9yOiBncmVlbjtcbn1cbjwvc3R5bGU%2BIn0%3D https://goog.space/?data=eyJ0eXBlIjoidGV4dCIsInZhbHVlIjoiIyB...
- arnorhs 4y agoThis is an interesting approach. Should help mitigate the URL max length for larger states. However as some people have pointed out it comes with a few caveats - The URL is unreadable for humans - You possibly end up storing things in the URL you did not intend - For smaller data sets the URL actually becomes larger than the URL params equivalent - You end up having to deal with version issues, possibly even URL string migrations as the code evolves I'm sure there still are use cases where this makes sense, but for most applications this ends up being overly complex
- surume 4y agoJust thinking - are there any security implications to this? Could sensitive data accidentally get added to the URL and then get intercepted?
- yurishimo 4y agoSure, but then I think most people would argue that you shouldn't store any of that state in the URL. It definitely is not a panacea.
- chrismsimpson 4y agoASP.NET WebForms did this and it was horrible.
- OOPMan 4y agoHmmmmmm....combine this with a link shortener and you have much the same effect except the actual state gets stored elsewhere. Which is totally missing the point and being intentionally daft but it is a little amusing XD
- aabbcc1241 4y agoDepending on how repeative the object keys are, you maybe able to save quite some spaces with compress-json [1]. Since the OP is using lz-string to do compression, I suppose the data should be repetitive. [1] https://www.npmjs.com/package/compress-json https://www.npmjs.com/package/compress-json