Лето начинается: водные развлечения, гриль на острове и новые маршруты в бутик-отеле «Заонежье»
Для гостей бутик-отеля «Заонежье» к новому сезону подготовлены лесные трассы для первых заездов на новых квадроциклах — они позволяют исследовать дикие уголки карельской тайги и скалистые берега озер. Велопрогулки по дорогам Заонежья стали еще комфортнее благодаря электробайкам, которые этой весной пополнили велопарк отеля.
В мае, в отеле открылся сезон водных развлечений: гостям доступны сапы, каяки и весельные лодки. В этом году пользование ими - комплементарное для всех гостей. Также появились новые маршруты для катеров по заливам Онежского озера.
Ресторан «Руна» представляет летнюю серию гриль-сетов, которые можно приготовить самостоятельно на одном из необитаемых островов или устроить барбекю на лужайке у дома. В меню — овощные и рыбные сеты, а также мясное ассорти.
Бутик-отель «Заонежье» приглашает к активному отдыху среди озер и северной природы Карелии.
Для гостей бутик-отеля «Заонежье» к новому сезону подготовлены лесные трассы для первых заездов на новых квадроциклах — они позволяют исследовать дикие уголки карельской тайги и скалистые берега озер. Велопрогулки по дорогам Заонежья стали еще комфортнее благодаря электробайкам, которые этой весной пополнили велопарк отеля.
В мае, в отеле открылся сезон водных развлечений: гостям доступны сапы, каяки и весельные лодки. В этом году пользование ими - комплементарное для всех гостей. Также появились новые маршруты для катеров по заливам Онежского озера.
Ресторан «Руна» представляет летнюю серию гриль-сетов, которые можно приготовить самостоятельно на одном из необитаемых островов или устроить барбекю на лужайке у дома. В меню — овощные и рыбные сеты, а также мясное ассорти.
Бутик-отель «Заонежье» приглашает к активному отдыху среди озер и северной природы Карелии.
Если ты веб-разработчик и юзаешь ИИ… ставь это!
Agent Skills от Addy Osmani (Google) для:
✓ Веб‑производительности
✓ Лучших практик
✓ Доступности (Accessibility)
✓ SEO
Для React, Vue, Angular, Astro или чего угодно.
@WebDev_Plus
Agent Skills от Addy Osmani (Google) для:
✓ Веб‑производительности
✓ Лучших практик
✓ Доступности (Accessibility)
✓ SEO
Для React, Vue, Angular, Astro или чего угодно.
$ npx add-skill addyosmani/web-quality-skills
@WebDev_Plus
👍3🤣1
Angular 22 теперь с собственным AI Agent Skill.
Установил один раз — и любой кодирующий агент сразу понимает:
✅Лучшие практики Angular 22
✅ Signals и Signal Forms
✅ Standalone Components
✅ Zoneless Angular
✅ Современная архитектура Angular
✅ Кодинг-конвенции Angular
Теперь агент думает как эксперт по Angular, а не просто генерирует общий код.
Установка:
AI эффективен только в контексте.
Для максимума подключите Angular 22 MCP Server и включите экспериментальные devserver задачи.
#Angular #Angular22 #AI #ClaudeCode #TypeScript #WebDev
@WebDev_Plus
Установил один раз — и любой кодирующий агент сразу понимает:
✅Лучшие практики Angular 22
✅ Signals и Signal Forms
✅ Standalone Components
✅ Zoneless Angular
✅ Современная архитектура Angular
✅ Кодинг-конвенции Angular
Теперь агент думает как эксперт по Angular, а не просто генерирует общий код.
Установка:
npx angular-cli-ai install-skill
AI эффективен только в контексте.
Для максимума подключите Angular 22 MCP Server и включите экспериментальные devserver задачи.
#Angular #Angular22 #AI #ClaudeCode #TypeScript #WebDev
@WebDev_Plus
Привет, Laravel-разработчики
Начиная с Laravel v13.15.0, во фасаде Cache появился новый метод
По сути, этот метод делает две вещи.
Сначала он проверяет, существует ли указанный ключ в кэше. Если ключ найден, метод просто возвращает сохранённое значение. Если ключа нет, выполняется callback, а его результат сохраняется в кэше под этим ключом.
Это полностью совпадает с поведением существующего метода
Но у
Один из полезных сценариев применения — отправка клиенту собственного HTTP-заголовка с информацией о статусе кэша.
Например, можно явно указывать, был ли ответ получен из кэша (
#laravel #php
@WebDev_Plus
Начиная с Laravel v13.15.0, во фасаде Cache появился новый метод
rememberWithState().По сути, этот метод делает две вещи.
Сначала он проверяет, существует ли указанный ключ в кэше. Если ключ найден, метод просто возвращает сохранённое значение. Если ключа нет, выполняется callback, а его результат сохраняется в кэше под этим ключом.
Это полностью совпадает с поведением существующего метода
remember().Но у
rememberWithState() есть дополнительная возможность: вместе со значением он возвращает булевый флаг (true или false), который показывает, было ли значение уже в кэше или оно было сгенерировано только что.Один из полезных сценариев применения — отправка клиенту собственного HTTP-заголовка с информацией о статусе кэша.
Например, можно явно указывать, был ли ответ получен из кэша (
cache hit) или сформирован заново (cache miss).#laravel #php
@WebDev_Plus
Следующий урок, который мы усвоили при масштабной эксплуатации Laravel Scout:
Если в Scout включены очереди, индексация моделей выполняется через фоновые задачи, которые ставятся в очередь при вызове
В нагруженных приложениях могут возникать две ситуации:
одна и та же модель может сохраняться несколько раз за короткий промежуток времени;
очередь Scout может накапливаться, пока воркеры постепенно обрабатывают задачи.
В обоих случаях в очередь попадает множество дублирующихся задач на индексацию одной и той же модели ещё до того, как воркер успеет обработать первую из них.
Это создаёт лишнюю нагрузку, поскольку во время обработки задачи актуальная версия модели заново загружается из базы данных. В итоге каждая дублирующаяся задача повторно получает и индексирует одно и то же финальное состояние модели.
Чтобы решить эту проблему, я отправил PR (который был принят), добавляющий две новые задачи, которые можно включить по желанию. Они реализуют интерфейс
Таким образом, пока задача индексации конкретной модели находится в очереди, новые дублирующиеся задачи для неё создаваться не будут. Это уменьшает количество лишней работы, снижает нагрузку на очередь и сокращает число ненужных операций индексации.
@WebDev_Plus
Если в Scout включены очереди, индексация моделей выполняется через фоновые задачи, которые ставятся в очередь при вызове
$model->save().В нагруженных приложениях могут возникать две ситуации:
одна и та же модель может сохраняться несколько раз за короткий промежуток времени;
очередь Scout может накапливаться, пока воркеры постепенно обрабатывают задачи.
В обоих случаях в очередь попадает множество дублирующихся задач на индексацию одной и той же модели ещё до того, как воркер успеет обработать первую из них.
Это создаёт лишнюю нагрузку, поскольку во время обработки задачи актуальная версия модели заново загружается из базы данных. В итоге каждая дублирующаяся задача повторно получает и индексирует одно и то же финальное состояние модели.
Чтобы решить эту проблему, я отправил PR (который был принят), добавляющий две новые задачи, которые можно включить по желанию. Они реализуют интерфейс
ShouldBeUniqueUntilProcessing, который не позволяет ставить в очередь задачи для моделей, уже ожидающих индексации в очереди.Таким образом, пока задача индексации конкретной модели находится в очереди, новые дублирующиеся задачи для неё создаваться не будут. Это уменьшает количество лишней работы, снижает нагрузку на очередь и сокращает число ненужных операций индексации.
@WebDev_Plus
Когда в Node.js появляются тяжёлые вычислительные задачи, производительность приложения может заметно просесть.
Из-за этого многие делают вывод, что Node.js плохо подходит для таких сценариев или что проблема в самом JavaScript. Но решение есть.
В этом руководстве от Sumit Saha подробно разбирается многопоточность в Node.js с помощью Worker Threads.
Что внутри:
* зачем нужны Worker Threads;
* чем они отличаются от Event Loop;
* как выносить CPU-intensive задачи в отдельные потоки;
* обмен данными между потоками;
* практические примеры и паттерны использования.
Хороший материал для тех, кто хочет использовать все возможности Node.js и не блокировать основной поток тяжёлыми вычислениями.
https://freecodecamp.org/news/how-to-implement-multi-threading-in-nodejs-with-worker-threads-full-handbook/
@WebDev_Plus
Из-за этого многие делают вывод, что Node.js плохо подходит для таких сценариев или что проблема в самом JavaScript. Но решение есть.
В этом руководстве от Sumit Saha подробно разбирается многопоточность в Node.js с помощью Worker Threads.
Что внутри:
* зачем нужны Worker Threads;
* чем они отличаются от Event Loop;
* как выносить CPU-intensive задачи в отдельные потоки;
* обмен данными между потоками;
* практические примеры и паттерны использования.
Хороший материал для тех, кто хочет использовать все возможности Node.js и не блокировать основной поток тяжёлыми вычислениями.
https://freecodecamp.org/news/how-to-implement-multi-threading-in-nodejs-with-worker-threads-full-handbook/
@WebDev_Plus
freeCodeCamp.org
How to Implement Multi-Threading in Node.js With Worker Threads [Full Handbook]
JavaScript is a single-threaded programming language, and Node.js is the runtime environment for JavaScript. This means that JavaScript essentially runs within Node.js, and all operations are handled through a single thread. But when we perform tasks...
❤🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Этот инструмент проверяет производительность всего сайта.
Он сканирует все страницы и выставляет оценку каждой из них.
Что-то вроде Lighthouse, но с обзором всего сайта целиком.
Запуск:
@WebDev_Plus
Он сканирует все страницы и выставляет оценку каждой из них.
Что-то вроде Lighthouse, но с обзором всего сайта целиком.
Запуск:
npx unlighthouse --site <ваш-сайт>
@WebDev_Plus
Хочешь, чтобы твой AI-агент на Laravel использовал недорогую Gemini для простых диалогов, а при сложных задачах автоматически переключался на более мощную модель Claude?
Тогда стоит использовать динамическое переключение моделей
Переопределить модель по умолчанию можно прямо внутри метода
@WebDev_Plus
Тогда стоит использовать динамическое переключение моделей
Переопределить модель по умолчанию можно прямо внутри метода
prompt(). @WebDev_Plus
Нашёл UI-библиотеку, которая меня прям бесит.
Бесит, потому что всё должно работать именно так.
Oat:
→ 6KB CSS + 2.2KB JS
→ Ноль зависимостей
→ Не требует фреймворка
→ Без этапа сборки
→ Только семантический HTML
Пишешь
Пишешь
Пишешь
Никакого
Никаких
Просто HTML.
Доступность из коробки. Поддержка навигации с клавиатуры. Тёмная тема включена.
https://github.com/knadh/oat
@WebDev_Plus
Бесит, потому что всё должно работать именно так.
Oat:
→ 6KB CSS + 2.2KB JS
→ Ноль зависимостей
→ Не требует фреймворка
→ Без этапа сборки
→ Только семантический HTML
Пишешь
<button> — выглядит хорошо.Пишешь
<dialog> — выглядит хорошо.Пишешь
<input> — выглядит хорошо.Никакого
className="px-4 py-2 rounded-md bg-blue-500"Никаких
<Button variant="primary" size="md">Просто HTML.
Доступность из коробки. Поддержка навигации с клавиатуры. Тёмная тема включена.
https://github.com/knadh/oat
@WebDev_Plus
GitHub
GitHub - knadh/oat: Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library. ~8KB min+gz.
Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library. ~8KB min+gz. - knadh/oat
Твои AI API могут упасть. Лимиты запросов могут закончиться. Но приложение не обязано останавливаться из-за этого.
В #Laravel AI SDK достаточно передать массив провайдеров в аргумент
Если основной API недоступен, Laravel автоматически переключится на следующий провайдер в списке.
Никакой кастомной логики ретраев писать не нужно.👇
@WebDev_Plus
В #Laravel AI SDK достаточно передать массив провайдеров в аргумент
provider.Если основной API недоступен, Laravel автоматически переключится на следующий провайдер в списке.
Никакой кастомной логики ретраев писать не нужно.
@WebDev_Plus
Please open Telegram to view this post
VIEW IN TELEGRAM
Теперь документацию MDN и данные о совместимости браузеров можно подключить напрямую к AI-агенту или IDE и получать точные, актуальные ответы по веб-платформе.
Больше не нужно полагаться на устаревшие знания из обучающих данных модели.
Что даёт MDN MCP Server:
• прямой доступ к документации MDN;
• актуальные данные о поддержке API и веб-стандартов в браузерах;
• меньше галлюцинаций при работе с веб-разработкой;
• возможность использовать свежую информацию прямо в AI-агентах и редакторах кода.
Полезная штука для тех, кто использует Claude Code, Codex, Cursor и другие MCP-совместимые инструменты при веб-разработке.
@WebDev_Plus
Please open Telegram to view this post
VIEW IN TELEGRAM
15 мощных расширений для Chrome для разработчиков, дизайнеров и создателей контента
Loom — расширение для записи экрана, которое позволяет быстро записывать видео с экрана вместе с голосовыми комментариями и делиться ими.
Grammarly — ИИ-помощник для письма, который проверяет грамматику, орфографию, тон и читаемость текста прямо во время набора.
ColorZilla — инструмент для выбора цветов, позволяющий определять и копировать цвета с любых веб-страниц.
WhatFont — помогает быстро определить, какие шрифты используются на сайте.
Site Palette — генерирует цветовую палитру любого сайта для поиска дизайнерских референсов и вдохновения.
GoFullPage — делает полноразмерные скриншоты страниц без необходимости прокручивать их вручную.
Page Ruler — измеряет ширину и высоту элементов страницы в пикселях.
Lightshot — инструмент для быстрых скриншотов с возможностью редактирования и мгновенного обмена изображениями.
Imageye — находит все изображения на странице и позволяет быстро скачать их.
Responsive Viewer — помогает разработчикам проверять, как сайт выглядит на разных размерах экранов и устройствах.
CSS Viewer — показывает CSS-свойства элементов страницы при наведении курсора.
Web Developer — набор инструментов для веб-разработки, встроенный прямо в браузер.
JSON Viewer — форматирует и отображает JSON в удобном для чтения структурированном виде.
Lighthouse — автоматизированный инструмент от Google для анализа производительности сайта, доступности, SEO и соответствия лучшим практикам.
Wappalyzer — определяет технологии, фреймворки, CMS и другие инструменты, на которых построен сайт.
@WebDev_Plus
Loom — расширение для записи экрана, которое позволяет быстро записывать видео с экрана вместе с голосовыми комментариями и делиться ими.
Grammarly — ИИ-помощник для письма, который проверяет грамматику, орфографию, тон и читаемость текста прямо во время набора.
ColorZilla — инструмент для выбора цветов, позволяющий определять и копировать цвета с любых веб-страниц.
WhatFont — помогает быстро определить, какие шрифты используются на сайте.
Site Palette — генерирует цветовую палитру любого сайта для поиска дизайнерских референсов и вдохновения.
GoFullPage — делает полноразмерные скриншоты страниц без необходимости прокручивать их вручную.
Page Ruler — измеряет ширину и высоту элементов страницы в пикселях.
Lightshot — инструмент для быстрых скриншотов с возможностью редактирования и мгновенного обмена изображениями.
Imageye — находит все изображения на странице и позволяет быстро скачать их.
Responsive Viewer — помогает разработчикам проверять, как сайт выглядит на разных размерах экранов и устройствах.
CSS Viewer — показывает CSS-свойства элементов страницы при наведении курсора.
Web Developer — набор инструментов для веб-разработки, встроенный прямо в браузер.
JSON Viewer — форматирует и отображает JSON в удобном для чтения структурированном виде.
Lighthouse — автоматизированный инструмент от Google для анализа производительности сайта, доступности, SEO и соответствия лучшим практикам.
Wappalyzer — определяет технологии, фреймворки, CMS и другие инструменты, на которых построен сайт.
@WebDev_Plus
❤1
Кто сказал, что запуск больших моделей локально обязательно должен быть тяжёлым и раздутым?
Shimmy — это односоставный бинарник на Rust размером всего 5 МБ, который явно бросает вызов Ollama.
Что обещает проект:
→ один исполняемый файл размером 5 МБ
→ запуск примерно за 100 мс
→ потребление памяти около 50 МБ
→ 100% совместимость с OpenAI API
Если Ollama кажется слишком громоздким, а запускать локальные модели всё равно хочется — стоит присмотреться к Shimmy.
https://github.com/Michael-A-Kuykendall/shimmy
@WebDev_Plus
Shimmy — это односоставный бинарник на Rust размером всего 5 МБ, который явно бросает вызов Ollama.
Что обещает проект:
→ один исполняемый файл размером 5 МБ
→ запуск примерно за 100 мс
→ потребление памяти около 50 МБ
→ 100% совместимость с OpenAI API
Если Ollama кажется слишком громоздким, а запускать локальные модели всё равно хочется — стоит присмотреться к Shimmy.
https://github.com/Michael-A-Kuykendall/shimmy
@WebDev_Plus
GitHub
GitHub - Michael-A-Kuykendall/shimmy: ⚡ Pure-Rust WebGPU inference engine — OpenAI-API compatible, GGUF native, runs on any GPU.…
⚡ Pure-Rust WebGPU inference engine — OpenAI-API compatible, GGUF native, runs on any GPU. No Python. No llama.cpp. Single binary. - Michael-A-Kuykendall/shimmy
Фиксация сессии в PHP: если после входа пользователя не сменить идентификатор сессии, злоумышленник может заранее навязать жертве свой
Исправляется одной строкой:
Вызывать её нужно сразу после успешного логина.
Параметр
Если вызвать просто:
старый идентификатор останется валидным на диске. В таком случае заранее украденный или навязанный до авторизации cookie всё ещё может использоваться для доступа к старой сессии.
Большинство современных фреймворков выполняют ротацию идентификатора сессии автоматически, но при работе с чистым PHP это нужно делать самостоятельно.
@WebDev_Plus
PHPSESSID, а после её авторизации получить доступ к уже аутентифицированной сессии. Исправляется одной строкой:
session_regenerate_id(true);
Вызывать её нужно сразу после успешного логина.
Параметр
true здесь важен: он удаляет старый файл сессии.Если вызвать просто:
session_regenerate_id();
старый идентификатор останется валидным на диске. В таком случае заранее украденный или навязанный до авторизации cookie всё ещё может использоваться для доступа к старой сессии.
Большинство современных фреймворков выполняют ротацию идентификатора сессии автоматически, но при работе с чистым PHP это нужно делать самостоятельно.
@WebDev_Plus
Выводи типы из значений в TypeScript.
То есть не дублируй руками union-типы вроде:
Лучше задай объект один раз, а тип получи из него:
Теперь
Если потом добавишь новую роль в
@WebDev_Plus
То есть не дублируй руками union-типы вроде:
type Role = "system_admin" | "content_editor" | "guest_viewer";
Лучше задай объект один раз, а тип получи из него:
type ValueOf<T extends Record<PropertyKey, unknown>> = T[keyof T];
const USER_ROLE = {
Admin: "system_admin",
Editor: "content_editor",
Viewer: "guest_viewer",
} as const satisfies Record<string, string>;
type Role = ValueOf<typeof USER_ROLE>;
Теперь
Role автоматически равен:"system_admin" | "content_editor" | "guest_viewer"
Если потом добавишь новую роль в
USER_ROLE, тип обновится сам.@WebDev_Plus
This media is not supported in your browser
VIEW IN TELEGRAM
Блин... Этот open-source HTML Email Builder просто огонь
Это SDK для визуальной сборки email-шаблонов через drag-and-drop. Пользователи могут создавать письма без необходимости писать HTML-код с нуля.
→ визуальный email-конструктор с drag-and-drop
→ готовые email-компоненты
→ настраиваемые макеты писем
→ экспорт в HTML, MJML или JSON
Отлично подойдёт для SaaS-продуктов, e-commerce, CRM-систем, маркетинговых платформ и любых приложений, где нужно создавать email-шаблоны.
Исходники : github.com/templatical/sdk
@WebDev_Plus
Это SDK для визуальной сборки email-шаблонов через drag-and-drop. Пользователи могут создавать письма без необходимости писать HTML-код с нуля.
→ визуальный email-конструктор с drag-and-drop
→ готовые email-компоненты
→ настраиваемые макеты писем
→ экспорт в HTML, MJML или JSON
Отлично подойдёт для SaaS-продуктов, e-commerce, CRM-систем, маркетинговых платформ и любых приложений, где нужно создавать email-шаблоны.
Исходники : github.com/templatical/sdk
@WebDev_Plus
В PHP 8.4 появились две небольшие функции, которых разработчикам не хватало годами:
Теперь вместо циклов вроде:
можно написать:
А проверки "все элементы соответствуют условию" превращаются в:
Кода меньше, читается проще, намерение видно сразу.
Редкий случай, когда небольшое дополнение к языку реально убирает тонны однотипного шаблонного кода.
@WebDev_Plus
array_any() и array_all().Теперь вместо циклов вроде:
foreach ($items as $item) {
if (...) {
return true;
}
}
return false;можно написать:
return array_any($items, fn ($item) => ...);
А проверки "все элементы соответствуют условию" превращаются в:
return array_all($items, fn ($item) => ...);
Кода меньше, читается проще, намерение видно сразу.
Редкий случай, когда небольшое дополнение к языку реально убирает тонны однотипного шаблонного кода.
@WebDev_Plus
🔥 Laravel Tip
В Laravel есть встроенный способ защититься от дублирующихся задач в очередях — интерфейс
Достаточно реализовать метод
Если задача с таким идентификатором уже находится в очереди, Laravel не поставит её повторно.
Меньше ручных проверок, меньше блокировок и меньше гонок данных. Особенно полезно для синхронизации пользователей, обработки вебхуков и фоновых задач, которые могут запускаться несколько раз подряд.
@WebDev_Plus
В Laravel есть встроенный способ защититься от дублирующихся задач в очередях — интерфейс
ShouldBeUnique.Достаточно реализовать метод
uniqueId() и вернуть уникальный идентификатор задачи:class SyncUser implements ShouldQueue, ShouldBeUnique
{
public function uniqueId(): string
{
return $this->userId;
}
}
Если задача с таким идентификатором уже находится в очереди, Laravel не поставит её повторно.
Меньше ручных проверок, меньше блокировок и меньше гонок данных. Особенно полезно для синхронизации пользователей, обработки вебхуков и фоновых задач, которые могут запускаться несколько раз подряд.
@WebDev_Plus