Skip to main content

Things I Learned: Using URLs to Store Web App State in Cesium Sandcastle

 With Cesium Ion Sandcastle users can try out various parts of the Cesium JS library to create maps. Once their code is working, they can also share those maps with the code. I initially wondered about the infrastructure that required to store and then serve every single map examples code. Then, I realized that the code isn't stored in a server, it's in the share URL!

I originally started to put this together when I noticed how long a typical Cesium Sandcastle is. They tend to look like this:


except longer. The seemingly random characters are a base64 encoded transcript of the JavaScript code along with the html and styling for the Sandcastle project.

The fact that everything was encoded in the URL made me wonder what else could be achieved with the URL. A lot, it turns out.

NOTE: I discovered it's important to place your additional URL args before the #c anchor that contains the Sandcastle code. Otherwise, your args get interpreted as being part of the JavaScript that's loaded from the URL.

Storing CZML Map Links

My first foray into storing state in the URL was to store the address of the czml map I wanted to visualize. By doing that, I could build map viewing apps and then supply any of my czml maps to take a look at within the apps. I pass the location of the map a URL argument to my Sandcastle JavaScript like this:

https://sandcastle.cesium.com/standalone.html?mapurl=https://raw.githubusercontent.com/hcarter333/rm-rbn-history/refs/heads/main/maps/sw_qso.czml

I then retrieve the map location in JavaScript using

    function getParam(name) {
      const source = window.location.search.length > 1
        ? window.location.search.substring(1)
        : window.location.hash.slice(1);
      const p = new URLSearchParams(source);
      return p.get(name);
    }

    const mapurl2 = getParam("mapurl");
    console.log("CZML URL:", mapurl2);

When using the map viewer in the Sandcastle code editor development window, this won't work, but once the map is full screen it absolutely does. It has to do with where the 'window' object is stored within the DOM.

Encoding Camera Views

This is the use for URL arguments that has me writing this post this week. Cesium maps are awesome! I love that I can get a view just so and watch QSOs animate on the map in the same order they occurred during a radio outing. Sometimes, I also get very cool views of things in the geography of the two stations that would effect propagation. Sharing those views is difficult. I have to tell the person where and how to look. That got me wondering if there was a way to share the camera views as well.

There is!

With a little help from GPT5, I can now pass camera parameters, including look angles, via a single URL argument. I asked GPT5 for

Here's the current version of the code you generated above. I'd like for users to be able to store camera positions and view angles for the two views. Please add a save button to the view. When clicked, it should present a hyperlink to a new URL described below that the user can click. Here's what it should do 

1. Store the entire camera and look information for both panels. That information should be base 64 encoded and placed in the new URL as panelview= and subpanelview= 

2. Modify the code so that if panelview and subpanelview args are contained in the url (the new code should look for them the same way the existing code looks for the mapurl) the camera for the each respective view should be flown so that the exact view the user had when they clicked on save is restored. 

3. Also save the vh and vw settings of the subpanel in subpanelsize and resize it to its original extent if the subpanelsize arg is present in a url 

As an example, here is the current url https://sandcastle.cesium.com/standalone.html?mapurl=https://raw.githubusercontent.com/hcarter333/rm-rbn-history/refs/heads/main/maps/2025_08_20_flat_us_4571.czml#c=zVZtb9s2EP4rnLuhCmDLSQYMne14a9MCzeCgwex1wOAPpaizRIQiBZKy4wT97ztSkvVipyiQfZi/WLyX55473p1ECCGbQjLLlSQJ2DuqaRZImsEZ...  and so on

And that's kind of, sort of what I got! I had to massage this code a bit more than usual because the ChatGPT web site had defaulted me back to the 4o model. I'll write about that more soon, but still! I can now save views and timestamps, specify what czml file the Cesium app should use, and have the map come up in the exact view so the user doesn't have to navigate to get to the starting point!

Notice that I used base64 encoding. I thought this would make for a slightly shorter URL. I'm not sure I pulled that off. However, using this encoding, I at least never have to worry about converting characters so they'll work properly in a URL.

I'm impressed that GPT5 decided to bundle the view information up as JSON. I know the JSON format, so if I ever have to dig through that portion of the code it won't be a big deal for me. The fact that JSON is widely used should also mean that other maintainers should have an easier time of things as well.

Getting the URL to the User

For now, I'm using a 'Save View' button that's hidden by default. When I click the button, my JavaScript code creates a new URL with updated view information, and then adds that URL as a hyperlink to the button's panel. 



From there, I can copy the address and share it around as much as I like.

The final bit of code I wrote was to check for a URL argument 

hideSave=1

so that the code could hide the 'SaveView' button for maps that are deployed on the blog, for example.


What's Next?

I'm moving closer and closer to trying an implementation of my old ham radio practice exam app that is hosted statically with all the users scores and other information encoded in a URL that they save to start practicing again next time!





Comments

Popular posts from this blog

Cool Math Tricks: Deriving the Divergence, (Del or Nabla) into New (Cylindrical) Coordinate Systems

Now available as a Kindle ebook for 99 cents ! Get a spiffy ebook, and fund more physics The following is a pretty lengthy procedure, but converting the divergence, (nabla, del) operator between coordinate systems comes up pretty often. While there are tables for converting between common coordinate systems , there seem to be fewer explanations of the procedure for deriving the conversion, so here goes! What do we actually want? To convert the Cartesian nabla to the nabla for another coordinate system, say… cylindrical coordinates. What we’ll need: 1. The Cartesian Nabla: 2. A set of equations relating the Cartesian coordinates to cylindrical coordinates: 3. A set of equations relating the Cartesian basis vectors to the basis vectors of the new coordinate system: How to do it: Use the chain rule for differentiation to convert the derivatives with respect to the Cartesian variables to derivatives with respect to the cylindrical variables. The chain ...

The Valentine's Day Magnetic Monopole

There's an assymetry to the form of the two Maxwell's equations shown in picture 1.  While the divergence of the electric field is proportional to the electric charge density at a given point, the divergence of the magnetic field is equal to zero.  This is typically explained in the following way.  While we know that electrons, the fundamental electric charge carriers exist, evidence seems to indicate that magnetic monopoles, the particles that would carry magnetic 'charge', either don't exist, or, the energies required to create them are so high that they are exceedingly rare.  That doesn't stop us from looking for them though! Keeping with the theme of Fairbank[1] and his academic progeny over the semester break, today's post is about the discovery of a magnetic monopole candidate event by one of the Fairbank's graduate students, Blas Cabrera[2].  Cabrera was utilizing a loop type of magnetic monopole detector.  Its operation is in...

More Cowbell! Record Production using Google Forms and Charts

First, the what : This article shows how to embed a new Google Form into any web page. To demonstrate ths, a chart and form that allow blog readers to control the recording levels of each instrument in Blue Oyster Cult's "(Don't Fear) The Reaper" is used. HTML code from the Google version of the form included on this page is shown and the parts that need to be modified are highlighted. Next, the why : Google recently released an e-mail form feature that allows users of Google Documents to create an e-mail a form that automatically places each user's input into an associated spreadsheet. As it turns out, with a little bit of work, the forms that are created by Google Docs can be embedded into any web page. Now, The Goods: Click on the instrument you want turned up, click the submit button and then refresh the page. Through the magic of Google Forms as soon as you click on submit and refresh this web page, the data chart will update immediately. Turn up the:...