Are you annoyed by a trend in browsers to default to an annoying advertising page with new tabs? I sure am. And they don’t make it easy to change that. I thought, rather than a blank new tab page, why not load something cute and local. I enlisted claude.ai to help expedite the code and got something I like.
homepage.html is a very simple default page that loads a random image from a folder as a background, overlays the current local time in the one correct time format with seconds, live update, and throws up the local weather from wttr.in after a delay (to avoid hitting the server unnecessarily if you’re not going to keep the tab blank long enough to see the weather).
Images have to be in a local folder and in a predictable naming structure, as written “image_001.webp” to “image_999.webp.” If the random enumerator chooses an image name that doesn’t exist, you get a blank page.
Browsers don’t auto-rotate by exif (or webp) metadata, so orient all images in the folder as you’d like them to appear.
The weather information is only “current” which isn’t all that useful to me, I’d like tomorrows weather, but that’s not quite possible with the one-liner format yet.
Update, I added some code to display today and tomorrow’s events from your Thunderbird calendar, if you have it. If not, just don’t cron the bash script and no diff. I also changed the mechanism of updating the weather to a 30 minute refresh of the page itself, this way you get more pix AND the calendar data updates every 30 minutes. Web browsers and javascript are pretty isolated from the host device, you can’t even read a local file in most (let alone write one). All good security, but a problem if you want data from your host computer in a web page without running a local server to deliver it.
My work around was to write the data into the file itself with a script. Since the data being written is multi-line, I opted to tag the span for insert with non-breaking spaces, a weird character and the script sanatizes the input from calendar events extracted from the sqlite database in case some event title includes them. The current config is by default:
~/.myHomePage/myHomePage.html ~/.myHomePage/getEvents.sh ~/.myHomePage/myHomeImages/image_001.webp ~/.myHomePage/myHomeImages/image_002.webp etc.
The code for the executables, myHomePage.html
and getEvents.sh
, is below. The images you have to supply yourself.
How you set the homepage and new tab default page varies by browser. In Brave try hamburger→settings→appearance→show home button→select option→paste the location of the homepage.html file, e.g. file:///home/(username)/.myHomePage/myHomePage.html
The pictures are up to you, but here’s the code:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name='author' content='David Gessel, dg@brt.llc'> <meta name='summary' content='This is a nice homepage/new tab that shows some useful info and pix'> <meta name='url' content='https://gessel.blackrosetech.com'> <meta name='date' content='2024-05-16'> <title>New Tab</title> <style> body { margin: 0; padding: 0; height: 100vh; display: flex; justify-content: center; align-items: flex-start; overflow: hidden; } #background-image { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-size: cover; background-position: center; z-index: -1; } #time-date { position: absolute; top: 20px; right: 20px; font-size: 48px; color: white; text-shadow: 3px 3px 8px rgba(0, 0, 0, 1); font-family: sans-serif; font-weight: bold; } #events { position: absolute; top: 80px; right: 20px; font-size: 24px; color: white; text-shadow: 3px 3px 8px rgba(0, 0, 0, 1); font-family: sans-serif; text-align: right; } #weather { position: absolute; bottom: 20px; left: 20px; font-size: 24px; color: white; text-shadow: 3px 3px 8px rgba(0, 0, 0, 1); font-family: sans-serif; } </style> </head> <body> <div id="background-image"></div> <div id="time-date"></div> <div id="events"></div> <div id="weather"></div> <script> // Function to get a random image from the 'image_001.webp' to 'image_230.webp' range // Edit image folder to match the folder you want to store the images in // edit the min and max image index range to match the images // set the imageName extension to suit (e.g. .jpg, .webp, .png) // white screen usually means the images or folder can't be found function getRandomImage() { const imageFolder = 'myHomeImages/'; const minImageIndex = 1; const maxImageIndex = 230; const randomIndex = Math.floor(Math.random() * (maxImageIndex - minImageIndex + 1)) + minImageIndex; const imageName = `image_${randomIndex.toString().padStart(3, '0')}.webp`; return `${imageFolder}${imageName}`; } // Function to update the time and date display // Updates every second, uses the only technically correct* date and time format // * The best kind of correct. function updateTimeDate() { const dateTimeElement = document.getElementById('time-date'); const currentDate = new Date(); const year = currentDate.getFullYear(); const month = String(currentDate.getMonth() + 1).padStart(2, '0'); const day = String(currentDate.getDate()).padStart(2, '0'); const hours = String(currentDate.getHours()).padStart(2, '0'); const minutes = String(currentDate.getMinutes()).padStart(2, '0'); const seconds = String(currentDate.getSeconds()).padStart(2, '0'); // Get the day of the week in short form const daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; const dayOfWeek = daysOfWeek[currentDate.getDay()]; const formattedDateTime = `${dayOfWeek}, ${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; dateTimeElement.textContent = formattedDateTime; } // Function to display the events data function displayEvents() { const eventsElement = document.getElementById('events'); const eventsData = ` `; eventsElement.innerHTML = eventsData.replace(/\n/g, '<br>'); } // Function to fetch and display the weather information async function updateWeather() { const weatherElement = document.getElementById('weather'); try { await new Promise(resolve => setTimeout(resolve, 10000)); // 10-second delay const response = await fetch('https://wttr.in/?m&format=%l%20%c+%C+%t%20+%h%20+%w\n'); const weatherData = await response.text(); weatherElement.textContent = weatherData; } catch (error) { console.error('Error fetching weather information:', error); weatherElement.textContent = 'Error fetching weather information.'; } } // Set the random background image const backgroundImage = document.getElementById('background-image'); backgroundImage.style.backgroundImage = `url('${getRandomImage()}')`; // Update the time and date every second setInterval(updateTimeDate, 1000); // Display the events data displayEvents(); // Update the weather information updateWeather(); // Refresh the page every 30 minutes setInterval(() => { location.reload(); }, 1800000); // thanks to claude.ai for helping with the scripts. </script> </body> </html>
#!/bin/bash # this should extract today and tomorrow's events from your # Thunderbird calendar-data/<prefix>.sqlite file and then write them # into the events section of corresponding myHomePage.html file, which # will display them. Probably. # I use a remote calendar, so my local calendar file is cache.sqlite # but if you keep your events local, it should be local.sqlite. # Set the path to the Thunderbird local.sqlite database file # you need to replace the <provile> with yours like 432v2c4.username DB_PATH="$HOME/.thunderbird/<profile>/calendar-data/cache.sqlite" # Set the temporary database file path TEMP_DB_PATH="/tmp/local_temp.sqlite" # Set the output file path OUTPUT_FILE="$HOME/.myHomePage/myHomePage.html" # Set the temporary output file path TEMP_OUTPUT_FILE="/tmp/myHomePage_temp.html" # Get the current date and the date for tomorrow in the format used by Thunderbird, considering the local timezone TODAY=$(date -d "today 00:00:00" +%s)000000 TOMORROW=$(date -d "tomorrow 00:00:00" +%s)000000 # Create a temporary copy of the database cp "$DB_PATH" "$TEMP_DB_PATH" # Query the temporary database for today's events TODAY_EVENTS=$(sqlite3 -separator '|' "$TEMP_DB_PATH" "SELECT title, time(event_start/1000000, 'unixepoch', 'localtime') AS start FROM cal_events WHERE event_start >= $TODAY AND event_start < $TOMORROW") # Query the temporary database for tomorrow's events TOMORROW_EVENTS=$(sqlite3 -separator '|' "$TEMP_DB_PATH" "SELECT title, time(event_start/1000000, 'unixepoch', 'localtime') AS start FROM cal_events WHERE event_start >= $TOMORROW AND event_start < $TOMORROW + 86400000000") # Function to replace the last occurrence of "|" with "starts: " in each line replace_last_pipe() { while IFS= read -r line; do echo "${line%|*} starts: ${line##*|}" done } # Create the events data variable EVENTS_DATA="" # Check if there are today's events if [ -n "$TODAY_EVENTS" ]; then EVENTS_DATA+="Today's Events:\n$(echo "$TODAY_EVENTS" | replace_last_pipe)\n\n" fi # Check if there are tomorrow's events if [ -n "$TOMORROW_EVENTS" ]; then EVENTS_DATA+="Tomorrow's Events:\n$(echo "$TOMORROW_EVENTS" | replace_last_pipe)\n\n" fi # Remove any existing zero-width spaces from the events data EVENTS_DATA=$(echo "$EVENTS_DATA" | perl -pe 's/\xe2\x80\x8b//g') # Prefix and postfix the events data with zero-width spaces EVENTS_DATA=$(echo -e "\xe2\x80\x8b$EVENTS_DATA\xe2\x80\x8b") # Escape special characters in the events data EVENTS_DATA=$(echo "$EVENTS_DATA" | perl -pe 's/`/\\`/g; s/\//\\\//g') # Read the myHomePage.html file HTML_CONTENT=$(cat "$OUTPUT_FILE") # Replace the events data between the zero-width space delimiters with the updated events data HTML_CONTENT=$(echo "$HTML_CONTENT" | perl -0777 -pe 's/\xe2\x80\x8b.*?\xe2\x80\x8b/'"$EVENTS_DATA"'/s') # Check if the replacement was successful if [ $? -eq 0 ]; then # Write the updated HTML content to the temporary output file echo "$HTML_CONTENT" > "$TEMP_OUTPUT_FILE" # Move the temporary output file to the original output file mv "$TEMP_OUTPUT_FILE" "$OUTPUT_FILE" else echo "Error: Failed to update the events data in the HTML file." fi # Remove the temporary database file rm "$TEMP_DB_PATH"
And to collect the latest events and insert them in the above code, this bash script should work:
Then just set a cron script like <code>*/30 * * * * /home/<username>/.myHomePage/getEvents.sh</code> for regular updates.
Leave a Reply
You must be logged in to post a comment.