Alpha Stuff might still fundamentally change but this is it for new features for now.
This is a dashboard based loosely on hamdashboard. The configuration interface is "simplified" and it has a few more small features.
See the live output from the example at the bottom of the page here.
There are a couple good options.
-
Dump the files into a web server's static files root, or just open
index.htmldirectly in your browser. Opening the file directly from your local drive or vialocalhostmay cause issues with cross-origin restrictions. -
Use the docker image and mount your
config.jsin the container. Where the files are pre-dumped into a web server's static files root so you don't have to.
docker run -d -v <path to your config.js>:/usr/share/nginx/html/config.js -p <some free port>:80 ghcr.io/haxwithaxe/dashboard:latestservices:
dashboard:
image: ghcr.io/haxwithaxe/dashboard:latest
volumes:
- <path to your config.js>:/usr/share/nginx/html/config.js
ports:
- <some free port>:80
restart: unless-stoppedCurrently the only way to configure this dashboard is editing config.js. The application is expecting an Object named userSettings with the following keys.
topBar- AnObjectwith the configuration for the 3 sections of the top bar.columns(integer) - The number of columns in the tile grid.rows(integer) - The number of rows in the tile grid.feedScrollSpeed(number, optional) - The ticker scroll speed in pixels per second. Defaults to180.feeds(Array, optional) - A list of feed configurations. See Feeds for details.menu(Array, optional) - A list of user menu configurations. See Menu for details.tiles(Array) - A list of dashboard tile configurations. See Tiles for details.
A list of Objects with the following keys.
url(string) - An RSS or Atom feed URL.bgColor(string, optional) - Override the background color with an HTML color code.refreshInterval(interval, optional) - An interval (see Interval section below).textColor(string, optional) - Override the text color with an HTML color code.titleTextColor(string, optional) - Override the title text color with an HTML color code.
There is a static predefined menu and a user defined menu. Both are accessed via the menu button in the top right.
Back- Go backward in the interface.Refresh- Refresh the dashboard.Sources- Show the contents ofconfig.js.Help- Show a message about how to use the dashboard.Update- This button will appear when there is a newer version of the dashboard code available.
The user menu will appear as buttons below the predefined menu items.
The configuration is a list of Objects with the following options.
text(string) - The button text.url(string) - The URL to load when the button is clicked.bgColor(string, optional) - Override the button background color with an HTML color code.scale(number, optional) - The default CSStransformscale for the display of the loaded URL. Defaults to1.textColor(string, optional) - Override the button text color with an HTML color code.
The top bar contains a back button (far left), 3 text sections, and a menu button (far right).
Each section has the following options.
bgColor(string, optional) - Override the background color with an HTML color code.dateFormatTimeZone(string, optional) - IANA time zone to format the date and time with (eg"Etc/UTC"or"America/New_York"). Defaults to the browser's value.dateFormat(string, optional) - Cstrftimestyle date and time format. See the Date Formats section for details. Different defaults for each section.textColor(string, optional) - Override the text color with an HTML color code.text(string, optional) - Override the local date and time with static text.
By default the left section displays the local date and time with the format %A, %B %m - %H:%M:%S %Z.
By default the center section displays static text (the value of text).
By default the right section displays the UTC date and time with the format %Y-%m-%d - %H:%M:%S %Z.
"iso"- Format the time using ISO8601. Roughly equivalent to"%Y-%m-%dT%H:%M:%S.000Z"(not all the Cstrftimeoptions are implemented here).- A subset of the C
strftimestyle formatting is available.%Y- 4 digit year.%y- 2 digit year (00-99, eg25for the year2025).%m- 2 digit month (01-12).%e- 1-2 digit month (1-12).%b- Abbreviated month name.%B- Month name.%a- Abbreviated day of the week (egThufor Thursday).%A- Day of the week.%d- 2 digit day of the month (01-31).%e- 1-2 digit day of the month (1-31).%H- 2 digit hours (00-23).%k- 1-2 digit hours (0-23).%I- 2 digit hours (1-12).%l- 1-2 digit hours (1-12).%M- 2 digit minutes.%S- 2 digit seconds.%F- Equivalent to%Y-%m-%d.%T- Equivalent to%H:%M:%S.%R- Equivalent to%I:%M%r- Equivalent to%I:%M:%S.%p-AMorPM.%P- Lower case AM or PM (amorpm).%Z- Short timezone (egUTCforEtc/UTCorESTforAmerica/New_York).
%A, %B %m - %H:%M:%S %ZgivesWednesday, July 30 - 21:34:33 EDTfor Eastern Daylight Time at the moment of writing.%F - %T %Zgives2025-07-31 - 01:34:33 UTCfor UTC at the moment of writing.
Tiles are the boxes that display images, iframes, or videos on the dashboard.
The configuration is an Objects with the following options.
iframe(boolean, optional) - Iftruethe tile will default to being loaded as an iframe. Defaults tofalse.position(string|boolean, optional) - The default position of image sources within a tile that don't fill the tile. Iffalsethe default position0px 0pxis used. Otherwise all valid values for the CSS propertybackground-positionwill work. Defaults to"center".mimetype(string, optional) - Override the detected mimetype of a video sources by default.refreshInterval(interval, optional) - The interval (see Interval section below) to wait between refreshing the current source of this tile. Defaults tonull(no refreshing).rotateInterval(interval, optional) - The interval (see Interval section below) to wait between rotating the source being displayed in the tile. Defaults to"5m".scale(number, optional) - The default CSStransformscale for the sources in a tile. Defaults to1.sources- A list of sources to display one at a time in the tile. These can be URL strings orObjects with the following keys.title(string, optional) - The title to display at the top of the tile. If left out or set tonullor""the title will be hidden by default. Defaults tonull.video(boolean, optional) - Iftrueforce the sources to be treated like videos by default. Defaults tofalse.
The sources option for each tile can be a URL string, a list of URL strings, or a list of javascript objects with the options below.
A source given as a javascript object has the following options.
url- The URL to display when this source is active.iframe(boolean, optional) - Iftruethe tile will be loaded as an iframe while this source is displayed. Defaults toiframeof the tile.position(string|boolean, optional) - The default position of image sources within a tile that don't fill the tile. Iffalsethe default position0px 0pxis used. Otherwise all valid values for the CSS propertybackground-positionwill work. Defaults to thepositionset in the tile.mimetype(string, optional) - Override the detected mimetype of a video source.refreshInterval(interval, optional) - The interval (see Interval section below) to wait between refreshing this source. Defaults to therefreshIntervalof the tile or"5m".rotateInterval(interval, optional) - The interval (see Interval section below) to wait between rotating the source being displayed in the tile. Defaults to therotateIntervalof the tile.title(string, optional) - The title to display at the top of the tile. If left out or set tonullor""the title will be hidden. Defaults to thetitleset in the tile.video(boolean, optional) - Iftrueforce the source to be treated like a video. Defaults to thevideoset in the tile orfalse.
Some simple examples.
-
The following three configuration snippets are equivalent. They will each display a tile with one source having the URL
https://example.com/something.png.... sources: "https://example.com/something.png", ...
... sources: ["https://example.com/something.png"], ...
... sources: [{url: "https://example.com/something.png"}], ...
-
The following configuration snippet will display a tile with the title
Example, display the video with an unknown mimetype, and refresh every hour.... { mimetype: "", refreshInterval: "1h", sources: "https://example.com/example-video", title: "Example", video: true, } ...
Each tile is made up of one or more sources. The keys iframe, refreshInterval, rotateInterval, scale, title, mimetype, and video are all defaults for the sources given in sources. Individual sources can override the tile level settings. For instance, the following tile configuration:
...
{
title: "",
rotateInterval: "11m",
sources: [
{
url: "https://example.com/something.png",
refreshInterval: "1m",
},
{
url: "https://example.com/something-else.png",
rotateInterval: "5m",
},
]
}
...This will load something.png on dashboard page load, refresh every minute for 11 minutes when something-else.png will be loaded and not refresh at all for 5 minutes until the process repeats with something.png being loaded. The rotateInterval given in the source for something-else.png overrides the value given in the tile level.
Rotating and refreshing load the URL of the source anew. Bandwidth and compute aren't free. To avoid abusing the servers that host the files and pages that load in each tile it's best to set the refresh and rotate intervals as long as you can stand them. For instance a feed that is updated once a day can safely be loaded every 1 day or 12 hours if the content isn't time critical. Halving the time the source is updated at for the rotate or refresh interval is generally enough to capture the effect of the content being loaded every 30 seconds or less as long as changes aren't super time critical (See Nyquist-Shannon sampling). A source that updates every 15 minutes and provides a forecast for the next 24 hours can safely be loaded every 7.5 or 15 minutes. A source that updates once a day but changes are relevant in the first 10 minutes after the change would need to be loaded every 5 minutes to ensure changes are reflected within 10 minutes. A source that updates at a long interval but has content that requires action immediately on change (eg DX cluster or POTA activation update) is reasonable to refresh very frequently. Some services will update their sites automatically though so if the source is in an iframe you may not need to reload at all.
- Refresh means the content of the given tile or feed is reloaded without changing the source being displayed.
- Rotate (like a slide carousel) means the source being displayed is changed and loaded into the tile.
- The
rotateIntervalis the interval between the swapping of displayed sources. - The
refreshIntervalis the interval between refreshing a tile or feed. - If the
rotateIntervalof a tile is less than therefreshIntervaltherefreshIntervalis ignored. - If the
refreshIntervala tile is not set and the tile has only one source, therotateIntervalis effectively therefreshInterval.
Intervals are strings or numbers. Integers or floats are interpreted as milliseconds. Strings of numbers with the following suffixes are interpreted as described below.
s- Seconds. Example"5s"is 5 seconds.m- Minutes. Example"3m"is 3 minutes.h- Hours. Example"10h"is 10 hours.d- Days. Example"2d"is 2 days.w- Weeks. Example"1.5w"is one and a half weeks.
These can be combined in a single string. Example "1w2d3h4m5s" is an interval of 1 week, 2 days, 3 hours, 4 minutes, and 5 seconds combined.
const userSettings = {
topBar: {
center: {
text: "AB1CDE - AA00aa",
},
},
// Grid layout width and height
columns: 4,
rows: 3,
// Menu items
menu: [
{
text: "Lightning",
url: "https://map.blitzortung.org/",
},
{
text: "Weather",
url: "https://openweathermap.org/weathermap?basemap=map&cities=true&layer=temperature",
},
{
text: "Wind",
url: "https://earth.nullschool.net/#current/wind/surface/level/annot=fires",
},
{
text: "Space Weather",
url: "https://www.solarham.com/",
},
],
// Feed items
feeds: [
{
url: "https://www.amsat.org/feed/",
refreshInterval: "12h",
},
{
url: "https://daily.hamweekly.com/atom.xml",
refreshInterval: "1d",
},
],
// Dashboard tiles
tiles: [
{
title: "USA Forecast",
sources: "https://www.wpc.ncep.noaa.gov//noaa/noaa.gif",
refreshInterval: "1h",
},
{
title: "Local Radar",
sources: "https://radar.weather.gov/ridge/standard/KLWX_loop.gif",
refreshInterval: "15m",
},
{
title: "",
sources: [
{
title: "7 day",
url: "https://www.nhc.noaa.gov/xgtwo/two_atl_7d0.png",
},
{
title: "2 day",
url: "https://www.nhc.noaa.gov/xgtwo/two_atl_2d0.png",
},
{
title: "Today",
url: "https://www.nhc.noaa.gov/xgtwo/two_atl_0d0.png",
},
{
title: "Ocean",
url: "https://ocean.weather.gov/shtml/ira1.gif",
},
{
title: "GOES16-TAW",
url: "https://cdn.star.nesdis.noaa.gov/GOES16/ABI/SECTOR/taw/Sandwich/GOES16-TAW-Sandwich-900x540.gif",
},
],
},
{
title: "",
sources: "https://earth.nullschool.net/#current/wind/surface/level/annot=fires",
iframe: true,
rotateInterval: 0,
},
{
title: "NOAA D-RAP",
sources: "https://services.swpc.noaa.gov/images/animations/d-rap/global/d-rap/latest.png",
},
{
title: "foF2",
sources: "https://prop.kc2g.com/renders/current/fof2-normal-now.svg",
},
{
title: "MUF",
sources: "https://prop.kc2g.com/renders/current/mufd-normal-now.svg",
},
{
title: "GOES 16 SUVI",
sources: [
"https://services.swpc.noaa.gov/images/animations/suvi/primary/map/latest.png",
"https://services.swpc.noaa.gov/images/animations/suvi/primary/304/latest.png",
"https://services.swpc.noaa.gov/images/animations/suvi/primary/094/latest.png",
"https://services.swpc.noaa.gov/images/animations/suvi/primary/131/latest.png",
"https://services.swpc.noaa.gov/images/animations/suvi/primary/171/latest.png",
"https://services.swpc.noaa.gov/images/animations/suvi/primary/195/latest.png",
"https://services.swpc.noaa.gov/images/animations/suvi/primary/284/latest.png",
],
fit: "preserve",
},
{
title: "",
sources: "https://services.swpc.noaa.gov/images/swx-overview-large.gif",
refreshInterval: "30m",
},
{
title: "",
sources: [
"https://www.tvcomm.co.uk/g7izu/Autosave/HF_ZERO1_AutoSave.JPG",
"https://www.tvcomm.co.uk/g7izu/Autosave/ATL_HF10_AutoSave.JPG",
"https://www.tvcomm.co.uk/g7izu/Autosave/PACIFIC_HF_AutoSave.JPG",
],
fit: "preserve",
rotateInterval: "2m",
},
{
title: "",
sources: "https://www.hamqsl.com/solarbc.php",
refreshInterval: "1h",
},
{
title: "",
sources: "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4",
rotateInterval: "0",
},
],
}See the live output here.
