Initialize Fonrey Django multi-tenant project skeleton

Set up the required directory layout, app scaffolding, core settings, templates, static assets, and Docker/Tailwind tooling to establish a standardized development baseline.
This commit is contained in:
2026-04-26 17:12:09 +08:00
commit 4aba6dfa77
170 changed files with 1220 additions and 0 deletions

3
static/css/main.css Normal file
View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

49
static/js/main.js Normal file
View File

@@ -0,0 +1,49 @@
(function () {
if (window.Alpine && window.Alpine.plugin && window.Alpine.$persist) {
window.Alpine.plugin(window.Alpine.$persist);
}
function createToast(payload) {
var container = document.getElementById("toast-container");
if (!container || !payload || !payload.message) {
return;
}
var type = payload.type || "info";
var color = {
success: "border-success-600",
error: "border-danger-600",
warning: "border-warning-600",
info: "border-info-600",
}[type] || "border-info-600";
var item = document.createElement("div");
item.className = "bg-white border-l-4 " + color + " shadow-xs rounded px-4 py-3 text-sm min-w-[240px]";
item.textContent = payload.message;
container.appendChild(item);
window.setTimeout(function () {
item.remove();
}, 4000);
}
document.addEventListener("DOMContentLoaded", function () {
document.body.addEventListener("htmx:afterRequest", function (event) {
var xhr = event.detail && event.detail.xhr;
if (!xhr) {
return;
}
var trigger = xhr.getResponseHeader("HX-Trigger");
if (!trigger) {
return;
}
try {
var parsed = JSON.parse(trigger);
if (parsed["fonrey:toast"]) {
createToast(parsed["fonrey:toast"]);
}
} catch (_err) {
}
});
});
})();

0
static/vendor/alpine.min.js vendored Normal file
View File

0
static/vendor/flatpickr.min.css vendored Normal file
View File

0
static/vendor/htmx.min.js vendored Normal file
View File