Всё ядро Lemmy, по этому доступ к базе данных есть. В конфиге Lemmy можно поставить так, чтобы публиковать только данные своего сайта и будет автономный сайт. А можно сделать, что будут публиковать данные и с других сайтов… так вроде.
А выше код, к этому можно относиться, как к дизайну. Просто поменяли «пользовательскую» часть Lemmy.
Все обычно меняли дизайн Lemmy изменяя css, тут подошли капитально. Шаблоны все другие. Вот так, если упрощать.
Не взлетит пока не будет доступна установка на обычном хостинге/php
Я тоже ничего не понял… Ведь этот Lemmy — он же тоже есть на giithub… https://github.com/LemmyNet/lemmy
Может кто-то объяснить по простому как все это работает? И зачем мне проект по типу VC — если у меня нет контроля за базой данных… Так то вроде интересно все. Непонятно в чем фишка?
Раньше у меня было вот так: search.домен.ru. А на самом домене, в html, стояла просто форма поиска с отправкой именно на search.
api.sugata нужно делать и расположить там ещё поиск, чтобы форма была доступна на сайте, где только html. Тут идея заключается в том, чтобы в сам sugata, не заносить по возможности скрипты.
Я правильно понял что Sugata запускает перегинерацию всех объектов при изменении?
Мы можем выбирать, какие части проекта нам надо пересобрать. Но надо добавить вариант, генерацию только того, что изменено. А вот где всё по сегментам, сдалать шаг с задержкой.
Там много чего нет. У меня времени нет прежде всего. (
P.S. я не думаю, что стоит туда «сувать» JS.
было бы круто реализовать API для хранения реакций на записи, база уже есть на проекте
// emoji
const REACTION_EMOJI = {
like: "👍",
dislike: "🥱",
party: "🥳"
};
// иконки реакций
const REACTION_ICONS = {
like: "/assets/reactions/like.svg",
dislike: "/assets/reactions/dislike.svg",
party: "/assets/reactions/party.svg"
};
// API
const API_URL =
"https://api.sugata.ru/dev/posts/{slug}/likes";
// получаем slug поста из URL: /posts/my-post-slug
function getPostSlug() {
return document.location.pathname.match(/^\/posts\/([a-z0-9-_]+)/)?.[1];
}
// рендер списка реакций
function renderReactions(data, container) {
const html = Object.entries(data).map(([type, count]) => `
<li class="reactions__item reaction" data-type="${type}">
<button aria-label="Поставить реакцию ${type}">
<img
class="reaction__image"
src="${REACTION_ICONS[type]}"
alt="${REACTION_EMOJI[type]}"
width="64"
height="64"
/>
<div class="reaction__counter">
${count}
</div>
</button>
</li>
`);
container.innerHTML = html.join("");
}
// переключение активной реакции
function toggleReaction(container, selector, active) {
const item = container.querySelector(selector);
if (!item) return;
const img = item.querySelector(".reaction__image");
const counter = item.querySelector(".reaction__counter");
const button = item.querySelector("button");
if (active) {
item.classList.add("reaction_active");
button.setAttribute("aria-current", "true");
img.src = img.src.replace(".svg", ".gif");
counter.textContent = +counter.textContent + 1;
} else {
item.classList.remove("reaction_active");
button.removeAttribute("aria-current");
img.src = img.src.replace(".gif", ".svg");
counter.textContent = +counter.textContent - 1;
}
}
// === Инициализация ===
function initReactions() {
const container = document.querySelector(".reactions");
if (!container) return;
// стартовые значения
renderReactions({
shocked: 0,
love: 0,
like: 0,
dislike: 0,
rage: 0,
party: 0,
partyPopper: 0
}, container);
// загрузка данных с сервера
fetch(API_URL.replace("{slug}", getPostSlug()))
.then(r => r.json())
.then(data => {
renderReactions(data, container);
// обработчик кликов
container.addEventListener("click", (e) => {
const reaction = e.target.closest(".reaction");
if (!reaction) return;
const type = reaction.dataset.type;
// снимаем предыдущую активную
toggleReaction(container, ".reaction_active", false);
// активируем текущую
toggleReaction(container, `.reaction[data-type="${type}"]`, true);
// отправляем на сервер
fetch(API_URL.replace("{slug}", getPostSlug()), {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: JSON.stringify({ reactionId: type })
});
});
})
.catch(console.error);
}
document.addEventListener("DOMContentLoaded", initReactions);
По описанию интересный движок для ssg, попробую развернуть на выходных. Я для проектовы использую 11ty. Я правильно понял что Sugata запускает перегинерацию всех объектов при изменении? Нехватает только 404.html что бы не показывать серверное сообщение и можно прикрутить
self.addEventListener('fetch', event => {
event.respondWith(
caches.open(CACHE_NAME)
.then(cache => cache.match(event.request, { ignoreSearch: true }))
.then(response => response || fetch(event.request))
.catch(function() {
return caches.match('/offline.html');
})
);
});
что бы красота была)
+ Забыл еще спросить, не смотрели в сторону SQLite, на первый взгляд он идеально подошел бы сюда.
+ Еще обратил внимание что отсутствует sitemap.xml, очень жаль что он не генерируется(
Я хочу понять, что скрывается под словом «федерация». И я хочу понять что такое децентрализация и чем она отличается от той же libarea.
Ну если не понятно, так зачем париться и создавать федерацию. На гит есть ссылка на чат поддержки, можете обратиться, разработчик пояснит, как и что работает. Насчёт шлака я пояснил, можно отключать федерации, можно создать чисто свой сайт. Есть же libarea, создайте на ней сообщество и все, я создал себе, все что не нужно было отключил, сделал свой стиль и довольствуюсь, над стилем ещё конечно поработаю, времени не хватает.
Я всё равно нихера не понял.
Окей, то что лежит на гитхабе это интрфейс.
Я его запускаю у себя на vps и на моём сайте появляется всякий шлак, который строчат на какой-то Lemmy? или что?
Я хочу что бы пользователи регистрировались только у меня и писали/постили на моём сайте. Я не хочу получать какой-то мусор хер знает от кого на свой сайт.
Короче нихера не понял как это работает.
Так не я же его создавал, я нашел его и поделился.
Суть проекта: Rabotaem — это фронтенд (визуальная оболочка/клиент) для Lemmy. Lemmy — это аналог Reddit, работающий на протоколе ActivityPub (Fediverse).
Вот ответы на вопросы из комментария по пунктам:
1. «Я не понимаю, как это работает? БД отсутствует?»
База данных есть, но она находится на стороне бэкенда.
- Этот репозиторий (
rabotaem) — это только клиент (интерфейс), написанный на Svelte/SvelteKit. - Он подключается к серверу Lemmy (бэкенду). Именно бэкенд хранит все данные в базе данных (обычно PostgreSQL).
- Если устанавливать проект «с нуля», нужно поднимать и этот клиент, и бэкенд Lemmy (где и будет лежать БД).
2. «Если установить локально, то посты будут все равно распределятся по сети?»
Зависит от настройки бэкенда (Lemmy), к которому подключен клиент.
- Да, если включена федерация: Lemmy работает через протокол ActivityPub. Это значит, что ваш сервер может «общаться» с другими серверами (как e-mail: вы можете отправить письмо с gmail на mail.ru). Посты могут улетать на другие сервера, если пользователи оттуда подписаны на ваши сообщества.
- Нет, если закрыть сервер: В настройках Lemmy можно отключить федерацию (сделать «белый список» или полностью изолированный режим). Тогда посты останутся только у вас.
3. «Если кто-то установит и будет слать спам, такое можно отключить у себя?»
Да, можно.
- Владелец своего сервера (инстанса) имеет полные права модератора.
- Можно заблокировать конкретного пользователя.
- Можно заблокировать целый сервер (домен), с которого идет спам (это называется «дефедерация»). Спам с заблокированного сервера перестанет приходить к вам.
4. «Если владелец проекта удалит проект, то все данные исчезнут?»
Нет, данные не исчезнут.
- Код: Если автор удалит репозиторий на GitHub, исчезнет только источник обновлений кода. У вас останется ваша локальная копия, которая продолжит работать.
- Данные: Ваши посты и пользователи хранятся в вашей базе данных на вашем сервере. Автор кода не имеет к ним доступа. Это главное преимущество Open Source и децентрализации — вы владеете своими данными.
5. Про адаптивность (UI на мобилках)
Это форк клиента Photon, который изначально делался с упором на минимализм. Вероятно, текущая верстка еще дорабатывается, так как проект позиционируется для SEO-контента и блогов.
Поясните кто-нибудь что такое децентрализация в данном случае. Где файлы то хранятся?
это вряд ли, там сложный стек для обычного шареда)