Developer-focused knowledge base with practical code examples, error solutions, and step-by-step guides. Features instant full-text search powered by Meilisearch, Laravel backend with REST API, and Vue 3 SPA frontend.
Stack: Laravel 12 · Vue 3 · Meilisearch · Docker · MySQL
📸 Screenshots coming soon
База знаний по разработке: фиксируем проблемы, прикрепляем несколько решений (HTML/Markdown/код + PDF), быстро ищем их через Meilisearch и открываем в отдельном окне. Гости видят только публичные записи, авторизованные пользователи могут добавлять, редактировать и скачивать материалы.
- Поиск по проблемам и решениям (Laravel Scout + Meilisearch), мгновенная выдача на странице
/search. - Структура «проблема → решения» с якорями на конкретное решение
/problems/{problem}/{solution?}. - Богатый редактор (Quill), поддержка Markdown/HTML/кода, загрузка и скачивание PDF (
/solutions/{id}/download). - Пометка «в личные» (
personaly), чтобы ограничить показ гостям; гостям в Dashboard показываются только публичные проблемы. - Удобные UI-фичи: раскрытие/сворачивание текста, просмотр в отдельном окне, подсчёт количества решений.
- Backend: PHP 8.2+, Laravel 12, Inertia.js, Laravel Scout, Laravel Horizon (под очередь), Sanctum.
- Frontend: Vue 3, Vite, TailwindCSS, Quill/TipTap/Monaco/Prism.
- Поиск: Meilisearch (по умолчанию), можно переключить на другой драйвер Scout.
- Хранилище: публичный диск (
storage/app/public), скачивание черезStorage::disk('public'). - Инфраструктура: Docker Compose (php-fpm, nginx, MySQL, Meilisearch, phpMyAdmin).
- Скопируйте переменные:
cp .env.example .envи задайтеAPP_URL,APP_KEY(черезphp artisan key:generate). - Настройте БД: либо SQLite (
DB_CONNECTION=sqlite+database/database.sqlite), либо MySQL. Для Docker используйте значения изdocker-compose.yml(DB_HOST=db, DB_DATABASE=programm_pedia_db, DB_USERNAME=laravel, DB_PASSWORD=secret). - Настройте поиск:
SCOUT_DRIVER=meilisearch,MEILISEARCH_HOST=http://localhost:7700,MEILISEARCH_KEY=<ваш_ключ>(см. docker-compose переменнуюMEILISEARCH_KEY). - Установите зависимости:
composer installиnpm install. - Примените миграции и создайте симлинк стораджа:
php artisan migrate php artisan storage:link
- Запустите Meilisearch (например,
docker compose up -d meilisearch) и очередь (php artisan queue:listen --tries=1).
- Вариант «all-in-one»:
composer dev(поднимет php artisan serve, queue:listen, pail логи и Vite). - Вручную: в одном окне
php artisan serve, в другомphp artisan queue:listen --tries=1, в третьемnpm run dev. - Продакшн-сборка фронта:
npm run build.
- Соберите и запустите сервисы:
docker compose up -d(поднимет app, nginx, db, meilisearch, phpmyadmin). - Приложение будет доступно на
http://localhost:8033, phpMyAdmin —http://localhost:8086, Meilisearch —http://localhost:7700. - Выполните миграции внутри контейнера приложения:
docker compose exec app php artisan migrate.
/— лендинг./about— описание проекта./search?q=— поиск по проблемам/решениям./dashboard— управление проблемами/решениями (добавление, редактирование, загрузка PDF; авторизация обязательна)./problems/{problem}/{solution?}— детальная страница проблемы и выбранного решения./solutions/{solution}/download— скачивание прикреплённого PDF.
Problem:slug,title,description,metadata (json),personaly,user_id; связьhasManyсsolutions.Solution:problem_id,slug/title,content,markdown,code,language,pdf_path,summary,environment,root_cause,steps,verification,pitfalls,links,score,personaly,user_id; связи с тегами (tech_tags) и коллекциями.- Индексация Scout включает базовые поля и счётчики для релевантности.
- Файлы PDF сохраняются в
storage/app/public/solutions; убедитесь, что публичный диск опубликован (storage:link).
- Локально с SQLite:
./bin/setup.sh --sqlite(скопирует.env, проставит APP_URL, MEILISEARCH_*, выполнит composer/npm install, key:generate, migrate, storage:link). - Локально с MySQL:
./bin/setup.sh(использует текущие DB_* или оставляет их как есть). - Docker-стек:
MEILISEARCH_KEY=<ключ> ./bin/setup.sh --docker(запуститdocker compose up -d, поставит зависимости внутриapp, прогонит key:generate/migrate/storage:link, на хосте —npm install). APP_URL по умолчанию будетhttp://localhost:8033. - Опции:
--app-url=...,--meili-key=...,--skip-frontend(пропуститьnpm install),--reset-meili(Docker: сбросить volumemeili_data, если версия движка не совпадает — удалит индексы).
- Бэкенд:
composer test(очистка конфига происходит в скрипте). - Убедитесь, что Meilisearch запущен, если тесты используют Scout.
- Гости в
Dashboardвидят только проблемы безpersonalyили сpersonaly=false. Авторизованные видят всё. - Страница решений позволяет открывать материал в отдельном окне и привязывать ссылку к конкретному ID (
#solution-{id}). - Очередь по умолчанию —
database; не забудьте запустить воркер при использовании загрузки файлов.
- Подготовить окружение: PHP 8.2+, Composer, Node 18+, NPM; MySQL 8 (или SQLite для локалки); Meilisearch (порт 7700, ключ).
- Скопировать конфиги: cp .env.example .env; проставить APP_URL, APP_KEY (php artisan key:generate), DB_*, SCOUT_DRIVER=meilisearch, MEILISEARCH_HOST=http://localhost:7700, MEILISEARCH_KEY=<ключ>.
- Установить зависимости: composer install и npm install.
- Мигрировать БД и сторедж: php artisan migrate, php artisan storage:link.
- Запустить сервисы: поднять Meilisearch; если MySQL локально — запустить; если Docker — docker compose up -d (будут app+nginx+db+meili+phpmyadmin).
- Сборка фронта: для разработки — npm run dev; для продакшена — npm run build и настроить Vite/php artisan serve или nginx на /public.
- Очереди: php artisan queue:listen --tries=1 (Horizon подключён, можно использовать его).
- Проверка: зайти на / (лендинг), /dashboard (добавление проблем/решений), /search (поиск должен отдавать результаты после индексации Scout в Meilisearch), скачать PDF по /solutions/{id}/download.
- Docker-вариант (самый простой для команды):
- docker compose up -d
- docker compose exec app php artisan migrate && php artisan storage:link
- Открыть http://localhost:8033 (phpMyAdmin на :8086, Meilisearch на :7700).
- Индексация: после наполнения базы при необходимости выполнить php artisan scout:sync-index-settings или php artisan scout:import "App
\Models\Problem" и ...Solution (когда Meili готова).
Если что-то не работает — чаще всего это: не запущен Meilisearch/очередь, нет APP_KEY, не создан storage:link, или неверные DB_*. MEILISEARCH_KEY=supersecret ./bin/setup.sh --docker
Использование через одну команду:
- Стандартно: MEILISEARCH_KEY=supersecret ./bin/setup.sh --docker
- Если ранее был старый volume и есть риск несовместимости: MEILISEARCH_KEY=supersecret ./bin/setup.sh --docker --reset-meili (индексы будут пересозданы, после запуска скрипт сам прогонит импорт).
Коротко: добавляем манифест, сервис-воркер и регистрацию SW, плюс настраиваем кеширование/иконки/HTTPS для пушей. Для Vite + Vue проще всего через vite-plugin-pwa.
Что сделать:
- Установить плагин (локально): npm install -D vite-plugin-pwa.
- В vite.config.js подключить:
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({ plugins: [ laravel({ input: 'resources/js/app.js', refresh: true }), vue({ /* ... / }), VitePWA({ registerType: 'autoUpdate', includeAssets: ['favicon.ico', 'robots.txt'], manifest: { name: 'ProgrammPedia', short_name: 'Pedia', start_url: '/', scope: '/', display: 'standalone', background_color: '#ffffff', theme_color: '#4B5563', icons: [ { src: '/pwa-192.png', sizes: '192x192', type: 'image/png' }, { src: '/pwa-512.png', sizes: '512x512', type: 'image/png' }, { src: '/pwa-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, workbox: { globPatterns: ['**/.{js,css,html,ico,png,svg}'], runtimeCaching: [ { urlPattern: ({ request }) => request.destination === 'document', handler: 'NetworkFirst', options: { cacheName: 'pages', networkTimeoutSeconds: 3 }, }, { urlPattern: ({ request }) => ['style','script','image','font'].includes(request.destination), handler: 'StaleWhileRevalidate', options: { cacheName: 'assets' }, }, ], }, }), ], })
- Положить иконки в public/ (pwa-192.png, pwa-512.png, pwa-maskable-512.png).
- Зарегистрировать SW в клиенте, например в resources/js/app.js:
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js').catch(console.error) }) }
(плагин сам сгенерирует sw.js/manifest.webmanifest и вставит линк в HTML; registration можно оставить для явной регистрации).
- Сборка: npm run build и убедиться, что в public/ появились manifest.webmanifest, sw.js, иконки.
- HTTPS: для установки на Android/desktop нужен HTTPS или localhost. Для продакшена — включить TLS (напр. через nginx/Cloudflare). Без HTTPS пуш-уведомления не заработают.
- Пуши: на сервере добавить WebPush (Laravel WebPush/FCM). Клиент: запросить разрешение, получить subscription через serviceWorkerRegistration.pushManager.subscribe, отправить на бек; сервер посылает уведомление через WebPush/FCM. На iOS Safari Web Push работает только на iOS 16.4+ и с ограничениями.
- Офлайн: Workbox NetworkFirst для Inertia-страниц даст кеш последних страниц; StaleWhileRevalidate для статики. Можно добавить fallback для offline (например, отдавать /offline.html из public/ для document).
- Тест: в Chrome DevTools → Application → Manifest/Service Workers → проверить “PWA installable”, “Add to home screen” на Android/Chrome.
Если нужно — могу внести эти правки в репо (vite.config.js + app.js + добавить иконки/конфиг кеша).