This is my version of the famous Logsday website (which is currently not publically available, which is why this project aims to be publically available).
You will be able to upload a devlog exactly once a week.
- To run the server,
cargo run - Entry point for the server is
src/main.rs Askama's templates (#[template(path = "index.html")]) live in./templatesdirectory- Note that
Askama's templates are not actually html files. They're.. templates. With{{ ... }}being replaced with stuff before being sent to the client.
- Note that
Axum's Router usesnest_service("/static", ServeDir::new("public"))to map requests to/staticto take from./publicdirectory. That way, any requests to CSS or JS will take from there.- The database is
./sqlite.db. Needs to be created manually. Before running you might need to set an env variableDATABASE_URL="sqlite:sqlite.db"orDATABASE_URL="~/logsday/sqlite.db"
/=>templates/landing.html- home, undecided/signup=>templates/signup.html/login=>templates/login.html/logout- logout and redirect to//mdguide=>templates/mdguide.html/u=>templates/viewuser.html- your profile; redirect to/loginwhen not logged in/u/{username}=>templates/viewuser.html- user's profile + list of their projects; when your page, give extra options/u/{username}/{project_slug}=>templates/viewproject.html- project page + list of logs; when your project, give extra options/u/{username}/{project_slug}/{log_number}=>templates/viewlog.html- log page; when your log, give extra options/new/project=>templates/newproject.html- create a new project; redirect to/loginwhen not logged in/new/log/{project_slug}=>templates/newlog.html- create a new log for the specified project; redirect to/loginwhen not logged in/new/media/{project_slug}- return a json list of existing files on GET; download the file and return a json of the uploaded file on POST; new log/new/media/{project_slug}/{log_number}- return a json list of existing files on GET; download the file and return a json of the uploaded file on POST; specified log/del/project/{project_slug}- delete the project; redirect to/loginwhen not logged in/del/log/{project_slug}/{log_number}- delete the log for the specified project; redirect to/loginwhen not logged in/del/media/{project_slug}/new/{file_name}- delete the given file from the newlog/del/media/{project_slug}/{log_number}/{file_name}- delete the given file from the specified log/uploads/{username}/{project_slug}/{log_number}/{filename}=>uploads/{username}/{project_slug}/{log_number}/{filename}- uploaded files for every log go here/static/*=>static/*- any static files that may be retrieved by the client (favicon, css/js, etc)/bits/navuser=>templates/bits/login.html/nav_user.html- get the navbar login/signup or the logout/time until logsday; bits uris are htmx helpers
- Database:
SQLite
- Web:
HTMXmarked.jslive markdown previewhighlight.jshighlighting code blocks
- Rust Crates:
axumfor web server basicsaksamafor template renderingargon2for password hashingpulldown-cmarkfor markdown to html renderingsqlxfor interacting with sqlite dbinferfor scanning magic bytes of filesimagefor converting image formatsscraperfor looking through html files for linked/embedded filestokio_cron_schedulerfor cron jobs from Rust, for nowtower_sessionsfor easy sessionsaxum_typed_multipartfor convenience, for now
- A lot of research for this project was done with Gemini. I don't think it's a big deal, but thought I'd put it here. It's just very convenient. And I don't need the nuiance of deep-diving into the topics yet. If capstone taught me something - I shouldn't be as afraid to just do something with a moderate amount of planning. Overplanning can be overwhelming and unproductive (to me).
POSTresponses should be either: Error message string (will be shown with htmx) or anHX_Redirectthat redirects to the new page. Any exceptions will be noted here and in the code.- Exception 1:
/new/media/...should return a json with{error}or{filename, filesize, filepath}
- Exception 1:
- Unix epoch starts on
Thu, Jan 1, 1970. For an 8-day week, Unix epoch starts onMon, Jan 1, 1970. In code, all weekdays are 0-indexed (Mon = 0, Tue = 1, etc). - You will not be able to private a project/log. You can unlist it, but not private.
- CommonMark spec
- server side uses
pulldown_cmarkwith the following options enabled
- server side uses
- Additional options:
- ENABLE_TABLES - idk the syntax for tables; may not be included later, if difficult to do
strikethrough
- Additional features:
represents a multimedia embed, depending on.ext. For supported extensions, refer tofilestuff::media_type
CREATE TABLE users (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
displayname TEXT NOT NULL,
password TEXT NOT NULL,
week_len INTEGER NOT NULL DEFAULT 8,
logsday_weekday INTEGER NOT NULL DEFAULT 3, -- Logsday is between Wednesday and Thursday; Monday is 0; Sunday is 6/7
schedule_last_changed INTEGER NOT NULL, -- when the user changed their Logsday selection last time; unix timestamp
admin BOOLEAN NOT NULL DEFAULT FALSE,
created_on INTEGER NOT NULL -- unix timestamp
);
CREATE TABLE projects (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
user_uid INTEGER NOT NULL,
title TEXT NOT NULL,
slug TEXT NOT NULL,
description TEXT,
created_on INTEGER NOT NULL, -- unix timestamp
UNIQUE(user_uid, slug)
FOREIGN KEY (user_uid) REFERENCES users(uid) ON DELETE CASCADE
);
CREATE TABLE logs (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
project_uid INTEGER NOT NULL,
title TEXT NOT NULL,
number INTEGER NOT NULL, -- this log's sequential number in the project
created_on INTEGER NOT NULL, -- unix timestamp
UNIQUE(project_uid, number)
FOREIGN KEY (project_uid) REFERENCES projects(uid) ON DELETE CASCADE
);