How to build a low-tech website
· in low-tech
nginx config tested with nginx -t and curl on Debian 13 (Docker) with nginx 1.26.3 and on nginx 1.29.8 (official Docker image); dithering command tested with ImageMagick 7.1.1-43 on Debian 13 (Docker); page weight measured on this site's own build, 5 November 2026.
This guide shows how to build a low-tech website that needs very little energy to serve: a static site with light pages, dithered images and no external scripts, served by nginx from a single-board computer at home. It also covers what Low-tech Magazine learned from running its website on a small solar panel, and what to expect when the power runs out.
What a low-tech website is
A low-tech website is designed around a limit, usually energy. Each page should take as little data, processing and power as possible to serve and to display. The best-known example is Low-tech Magazine's solar-powered site, launched in September 2018. It runs on a small computer on a balcony in Barcelona, powered by a solar panel and a battery, and it goes offline during long periods of bad weather.
The same ideas work for any small site you host at home, with or without solar power. Smaller pages load faster on slow connections and put less load on a slow home uplink. They also let a low-power board serve many visitors. The cost is a plainer design and, if you go fully off-grid, some downtime.
This guide builds on hosting a website from home, which covers installing the web server, port forwarding and HTTPS. For picking the hardware, see choosing home server hardware.
Start with a static site
A static site is a folder of ready-made HTML files. The web server only reads a file and sends it, with no database or code running for each request. That is the cheapest kind of website to serve, and it is what Low-tech Magazine uses.
A static site generator turns text files (usually Markdown) and a template into that folder of HTML. Low-tech Magazine started with Pelican, a generator written in Python. In 2023 it moved to Hugo, because rebuilding its 447 articles in several languages had become slow. Its write-up gives the numbers: on the solar server, a cached rebuild took 68 minutes 47 seconds with Pelican and 11 minutes 57 seconds with Hugo.
For a small site either works. Build on your laptop and copy the result to the server with rsync, so the low-power board only has to serve files:
# on your laptop, from the site folder
hugo --minify
rsync -av --delete public/ pi@server.local:/var/www/site/
Replace pi@server.local with your user and server address. The --delete option removes files on the server that no longer exist in your build.
Set a page weight budget
Page weight is the total size of everything a browser downloads to show a page: HTML, CSS, scripts, fonts and images. The HTTP Archive measured a median of 2,311 KB for pages on mobile and 2,652 KB on desktop in October 2024. Images were the largest part of home pages, and JavaScript was the largest part of inner pages.
Low-tech Magazine's 2018 redesign brought its average page down to 0.77 MB, which it reported as about five times smaller than its previous design. Its current about page gives an average below 0.5 MB.
Pick a budget before you design, and check every template against it. To measure a page:
- Open the page in Firefox or Chrome and open the developer tools (F12).
- Go to the Network tab, tick "Disable cache" and reload the page.
- Read the totals at the bottom. "Transferred" is what went over the network after compression. "Resources" or "size" is the uncompressed total.
For a quick check from the command line, curl can report the size of one file as sent with compression:
curl -so /dev/null -H 'Accept-Encoding: gzip' \
-w '%{size_download} bytes\n' https://example.org/
As an example, this guide's own page was measured on the day it was published, served with the nginx configuration further down. The HTML was about 28 KB, or 9.3 KB compressed. The CSS was 2.6 KB compressed and the JavaScript 0.7 KB. The two web fonts for the site name, menu and headings were 31 KB each and can't be compressed further. That makes about 77 KB transferred in total, and the fonts are more than 80% of it.
Make images small, or dither them
Images are usually most of a page's weight, so they give the biggest savings.
- Resize to the size you display. A photo straight from a phone is several thousand pixels wide. If your text column is 800 pixels wide, resize the image to 800 pixels.
- Use fewer images. Leave out decorative pictures, and use the same file for a thumbnail and the full image so browsers can cache it.
- Remove metadata. Camera data such as the model and GPS position adds bytes and can reveal where you live.
- Consider dithering. Low-tech Magazine converts its images to black and white with four levels of grey and adds colour in the browser. It reports these dithered images as about ten times less resource-intensive than its old ones. Since 2023, readers can switch dithering off for any image to see the original.
ImageMagick can do all of this in one command. This version resizes the image to 800 pixels wide, converts it to greyscale, applies an ordered dither with four grey levels and strips the metadata:
convert photo.jpg -resize 800x -colorspace Gray \
-ordered-dither o8x8,4 -strip photo-dithered.png
On Debian and Raspberry Pi OS, install it with sudo apt install imagemagick. Check the result with identify photo-dithered.png, which should report a greyscale image with four colours. Compare the file size with a normal resized JPEG, because how much dithering saves depends on the picture. Dithering also makes charts and diagrams hard to read, which Low-tech Magazine's 2023 rebuild notes too.
Fonts, CSS and JavaScript
Web fonts often weigh more than the text they display. Low-tech Magazine dropped its custom typeface and uses the browser's default font in a single weight, so no font file is downloaded at all. If you want something nicer than the default, a system font stack uses fonts already installed on the reader's device:
body {
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
max-width: 40em;
margin: 0 auto;
padding: 0 1em;
line-height: 1.5;
}
If you do use a web font, use one file in WOFF2 format, and only the weights you need.
Keep CSS to one small file. For JavaScript, the lowest-energy amount is none. A text site rarely needs any. If you add a feature that needs a script, such as a menu on phones, write it small and load it with defer.
Leave out third-party scripts and embeds: analytics, social media buttons, embedded videos, maps and comment widgets. Each one adds requests to other servers, and many track your readers. Low-tech Magazine runs no third-party tracking, no advertising services and no cookies. If you want visitor numbers, read your own server's access log.
Configure nginx for compression and caching
Two settings in the web server cut the data sent for every visit. Compression shrinks text files on the way out. Caching headers tell browsers to keep files they already have, so a returning visitor downloads only the HTML.
Put this in /etc/nginx/sites-available/site on the server, link it into sites-enabled, and replace example.org and the root path with your own:
server {
listen 80;
server_name example.org;
root /var/www/site;
index index.html;
# Compress text responses on the fly (HTML, CSS, JS, SVG, feeds).
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_vary on;
gzip_types text/css application/javascript image/svg+xml
application/atom+xml application/rss+xml text/plain;
# Serve a pre-compressed file.gz if it exists next to the original.
gzip_static on;
# HTML: browsers may keep a copy but must check for changes.
location / {
try_files $uri $uri/ =404;
add_header Cache-Control "no-cache";
}
# Images, fonts, CSS and JS: cache for 30 days.
location ~* \.(png|jpe?g|gif|webp|avif|svg|woff2|css|js)$ {
expires 30d;
add_header Cache-Control "public";
access_log off;
}
}
Then test and reload:
sudo ln -s /etc/nginx/sites-available/site /etc/nginx/sites-enabled/site
sudo nginx -t
sudo systemctl reload nginx
What the settings do:
gzip oncompresses responses whose type is listed ingzip_types. HTML is always included. Images are left out because PNG, JPEG and WebP are already compressed.gzip_static onsendspage.html.gzinstead of compressingpage.htmlagain for every request, if that file exists. Create the files once after each build withgzip -k -9, which keeps the original. This saves processor time on a slow board. Debian's nginx package is built with this module.no-cacheon HTML lets the browser store a page but makes it check with the server before using it, so readers see changes straight away. The check costs a small request, and the server replies "not modified" without the body when nothing changed.expires 30dlets browsers reuse images, fonts, CSS and scripts for 30 days without asking. If you change one of these files, give it a new name, or readers will keep the old copy until it expires.
This configuration passes nginx -t on Debian 13's nginx 1.26.3 and on nginx 1.29.8. Serving this site's own pages with it returned the compressed files and the headers described here, and a repeat request with the page's ETag got a 304 "not modified" reply. After a reload, check from another machine:
curl -sI -H 'Accept-Encoding: gzip' http://example.org/ | grep -i -E 'content-encoding|cache-control'
curl -sI http://example.org/style.css | grep -i -E 'expires|cache-control'
The first command should show Content-Encoding: gzip and Cache-Control: no-cache. The second should show an Expires date 30 days ahead and two Cache-Control lines, max-age=2592000 and public, which browsers combine. Use the path of a real CSS file on your site.
For HTTPS, follow the certificate steps in hosting a website from home and add the same compression and caching lines to the HTTPS server block.
Choose low-power hardware
A static site needs very little computing power. Low-tech Magazine's server is an Olimex A20 board with 1 GB of memory and 16 GB of storage. It draws between 1 and 2.5 watts depending on the number of visitors. In its first year it averaged 1.97 watts including all losses in the solar system, and served 865,000 unique visitors. That works out to 0.021 Wh per unique visitor.
Any current single-board computer, such as a Raspberry Pi, or an old laptop can serve a small static site. The hardware guide compares the options and their power use. A few choices keep the draw low:
- Use a wired network connection, and run the board without a screen or desktop environment.
- Don't run other services you don't need on the same board.
- Watch out for software updates that change power use. Low-tech Magazine's uptime dropped to about 80% for two months in late 2019 after a software upgrade raised the server's power use, and the site went down every night.
Don't forget the network equipment. Low-tech Magazine's server runs on solar power, but its router runs from the grid and uses 10 watts, several times more than the server.
Running on solar power
If you want to run the site from a solar panel, Low-tech Magazine's published figures are the most detailed real-world example.
| Period | Panel | Battery | Uptime |
|---|---|---|---|
| Dec 2018 to Nov 2019 | 50 W | 86.4 Wh lead-acid | 95.26% (399 hours offline) |
| First ten months of that period | 50 W | 86.4 Wh lead-acid | 98.2% |
| March to September 2020 | 30 W | 168 Wh lead-acid | 100% |
What the figures show:
- Half the energy is lost. In the first year the server used 9.53 kWh, but the charge controller recorded 18.10 kWh. The rest went to battery and conversion losses, so the system was about 50% efficient. Size your panel for twice what the server uses.
- Battery size sets how long bad weather you can survive. Low-tech Magazine estimated that each day of very bad weather needs about 47 Wh of storage. For 100% uptime over several years, it estimated a 440 Wh lead-acid battery, about the size of a car battery, to get through four days of poor weather.
- A bigger panel beats a bigger battery. The authors recommend a larger panel with a smaller battery. The battery lasts longer that way, and a larger panel still produces some power on cloudy days.
- Uptime costs embodied energy. Larger panels and batteries take more energy to make. In Low-tech Magazine's calculation, the configurations ranged from 10.92 kWh to 50.46 kWh of embodied energy per year. Aiming for 100% uptime can cost more energy than the server uses.
Low-tech Magazine's original target was 90% uptime, about 35 days offline a year. Deciding up front how much downtime you accept is what makes a solar site small.
When the server runs out of power
On Low-tech Magazine's setup, the charge controller cuts power to the server when the battery voltage drops below 12 volts. The site goes offline and comes back when the panel gets full sun again. The site shows a battery meter as the page background, and a power page with the battery level and a weather forecast, so readers can see why the site might be down.
If you build your own, plan for the shutdown:
- Shut down cleanly. A hard power cut while the board is writing can damage files on an SD card. Use a controller or a small script that shuts the board down before the battery voltage gets too low, and a board that starts again when power returns.
- Tell visitors. Show the battery level or a short note on the site, so a reader who finds it offline knows it is by design.
- Offer an offline copy. Readers can't reach a site that is down. An RSS or Atom feed lets them read new articles in their feed reader once they are fetched, and a downloadable archive or printed edition covers the rest. Low-tech Magazine publishes printed volumes of its archive.
- Keep feeds light. In its first year, 6.63 TB of Low-tech Magazine's 11.16 TB of traffic came from one broken RSS implementation. Check your access log for clients that fetch the same file again and again.
Measuring power use
Don't guess the power figure: measure it. Two simple tools cover a home setup:
- A plug-in energy meter between the wall socket and the power supply shows watts and total kWh, including the power supply's own losses. Leave it for a few days to get an average.
- A USB power meter between a USB power supply and the board shows the board's own draw.
Measure at idle and while you load the site with requests, and measure the router as well. Divide the energy used over a month by the number of visits in your access log to get your own energy per visit, the same way Low-tech Magazine calculated its 0.021 Wh per visitor.
Frequently asked questions
How much power does a solar-powered website use?
Low-tech Magazine's server draws between 1 and 2.5 watts, and averaged 1.97 watts in its first year including all solar system losses. That works out to 0.021 Wh per unique visitor.
What size solar panel and battery do I need for a website?
Low-tech Magazine ran on a 50 W panel and an 86.4 Wh battery with 95% uptime, and later reached 100% uptime from March to September 2020 on a 30 W panel and a 168 Wh battery. It estimated that a 440 Wh battery would be needed for 100% uptime over several years.
What happens to a solar-powered website when the battery runs out?
It goes offline. On Low-tech Magazine's setup, the charge controller cuts power when the battery drops below 12 volts, and the site comes back when the panel gets full sun again.
Why do low-tech websites use dithered images?
Dithering reduces an image to a few levels of grey. Low-tech Magazine reports its dithered images as about ten times less resource-intensive than its old ones, but how much dithering saves depends on the picture.
Can I host a static website on a Raspberry Pi?
Yes. A static site only needs the web server to read files and send them, which a single-board computer can do. Low-tech Magazine runs its site on an Olimex A20 board with 1 GB of memory.
What is a good page weight for a website?
There is no fixed number, but the HTTP Archive measured a median of about 2.3 MB for mobile pages in October 2024. Low-tech Magazine keeps its average page below 0.5 MB.
Sources
- Low-tech Magazine: How to Build a Low-tech Website? (September 2018)
- Low-tech Magazine: How Sustainable is a Solar Powered Website? (January 2020)
- Low-tech Magazine: Rebuilding a Solar Powered Website (June 2023)
- Low-tech Magazine: About the solar website (updated October 2024)
- Low-tech Magazine: power page
- HTTP Archive Web Almanac 2024: Page Weight
- nginx: ngx_http_gzip_module
- nginx: ngx_http_gzip_static_module
- nginx: ngx_http_headers_module (expires, add_header)
- ImageMagick: -ordered-dither
- Hugo and Pelican