Self-hostable uptime monitor and status page on Django: HTTP checks, Lighthouse audits, SEO crawls, and email and Discord alerts.
djangodockerhandcodedpythonself-hostedsqlitestatus-pageuptime-monitoringvite
1from django.shortcuts import render, redirect
2from django.http import HttpResponse
3
4from properties.models import Check, Property
5from accounts.models import User
6
7
8def home(request):
9 if request.user.is_authenticated:
10 return redirect('properties')
11
12 context = {}
13 context['title'] = 'Home'
14 context['description'] = 'Made by Isaac Bythewood, simple status for people who want to host their own and hack on it a bit.'
15
16 total_statuses = Check.objects.all().count()
17 context['total_statuses'] = total_statuses
18
19 total_properties = Property.objects.all().count()
20 context['total_properties'] = total_properties
21
22 total_users = User.objects.all().count()
23 context['total_users'] = total_users
24
25 try:
26 first_status_created_at = Check.objects.all().order_by('created_at').first().created_at
27 context['first_status_created_at'] = first_status_created_at
28 except AttributeError:
29 context['first_status_created_at'] = None
30
31 return render(request, 'pages/home.html', context)
32
33
34def changelog(request):
35 context = {}
36 context['title'] = 'Changelog'
37 context['description'] = 'An ongoing changelog and upcoming list of features for Status.'
38 return render(request, 'pages/changelog.html', context)
39
40
41def favicon(request):
42 # Heartbeat/pulse mark — a single EKG-style waveform sweep, reads as
43 # "vital signs / liveness" and is distinct from bars, rings, and shells.
44 svg = (
45 '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">'
46 '<polyline points="2,34 18,34 24,28 30,14 36,52 42,20 48,34 62,34" '
47 'fill="none" stroke="#6b9e78" stroke-width="6" '
48 'stroke-linejoin="round" stroke-linecap="round"/>'
49 '<circle cx="30" cy="14" r="3.5" fill="#c9a84c"/>'
50 "</svg>"
51 )
52 return HttpResponse(svg, content_type="image/svg+xml")
53
54
55def robots(request):
56 return render(request, 'robots.txt', content_type='text/plain')
57
58
59def sitemap(request):
60 return render(request, 'sitemap.xml', content_type='text/xml')