{"id":51236876,"url":"https://github.com/dcversus/conventions","last_synced_at":"2026-06-28T21:02:27.360Z","repository":{"id":63286560,"uuid":"500979568","full_name":"dcversus/conventions","owner":"dcversus","description":"Technical conventions format by Vasilisa Versus ","archived":false,"fork":false,"pushed_at":"2022-06-07T23:34:14.000Z","size":22,"stargazers_count":26,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-31T12:39:33.576Z","etag":null,"topics":["conventions","javascript"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dcversus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-07T19:36:39.000Z","updated_at":"2025-06-05T09:48:05.000Z","dependencies_parsed_at":"2022-11-16T09:50:25.542Z","dependency_job_id":null,"html_url":"https://github.com/dcversus/conventions","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dcversus/conventions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcversus%2Fconventions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcversus%2Fconventions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcversus%2Fconventions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcversus%2Fconventions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dcversus","download_url":"https://codeload.github.com/dcversus/conventions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dcversus%2Fconventions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34903523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conventions","javascript"],"created_at":"2026-06-28T21:02:25.097Z","updated_at":"2026-06-28T21:02:27.349Z","avatar_url":"https://github.com/dcversus.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Технические соглашения\nYet another формат описания технических соглашений by Vasilisa Versus. Использую его, чтобы собрать знания о проекте в одном месте, итеративно проводить рефакторинг, онбоардить новых сотрудников и на его базе фасилитировать обсуждения. Ценность состоит из: подхода к тому как с этим документом работать и самой структуры, которая наследуется из проекта в проект.\n\n## Структура\nКаждое правило имеет следующую структуру\n```md\n## Название секции\nКороткое описание секции, что к чему и почему. Если получится выразить в двух-трех тезисах, то идеально!\n\n### Материалы\n- [некая рекомендация №1](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)\n- [еще одна рекомендация](https://www.netflix.com/pt/title/81435684)\n- [третья рекомендация](https://youtu.be/dQw4w9WgXcQ)\n\n### Правила\n\u003cdetails\u003e\n  \u003csummary\u003eПравило 1\u003c/summary\u003e\n  \n  Такие правила могут быть спойлерами, внутри которых немного мотивации и примеров\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eПравило 2 под спойлером\u003c/summary\u003e\n  \n  Если их не много, то это приемлемо, но вы можете оценить читаемость исходника \n  Еще ниже будет пример собранного документа, который можно копипастить\n\u003c/details\u003e\n\n- Правило может быть и просто пунктом в списке\n- [А еще лучше конечно сделать его ссылкой](/section1/rule4.md)\n\n## Рецепты\n\u003cdetails\u003e\n  \u003csummary\u003eКак что-то сделать 1\u003c/summary\u003e\n  \n  Гайд может быть прям очень длинным, включать графику и описания шагов\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eГайд на что-то\u003c/summary\u003e\n  \n  Гайды конечно первые на разнесение в отдельные файлы\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eОчередной пример\u003c/summary\u003e\n\n  Я лично организовывала такое через яндексовую вики, в гитхабвики и confluence\n  Для большого проекта общее количество материалов было не больше 60 (около 2-3к строк)\n  Для небольших около 20 (500 строк)\n  Начинаю всегда с того чтобы держать в одном файле и разношу по мере необходимости.\n\u003c/details\u003e\n```\n\n## Как использовать\nКоротко гайд для старта:\n- Копипастим пример ниже в ваш проект или форкаем репу (или перенесите в вашу базу знаний, как удобнее, советую хранить с кодом)\n- Проходимся сверху вниз и заполняем секции правил для текущего состояния проекта\n- ЕСЛИ уже есть какие-то гайды, то собираем их в одном месте и причесываем. Если нет, то можно запланировать проработку хотя бы тех, которые есть в примере ниже\n- Постепенно накапливаем материалы для рекомендаций и обновляем и актуализируем\n\nДокумент в худшем случае заводится и овнится одним человеком который контролирует проект и его состояние. Нужно прилагать усилия, чтобы вовлекать его развивать и поддерживать коллективно, это обязательное условие к использованию. Об этом можно много писать, но если коротко критично минимально на документе завязать несколько процессов: онбоардинг, код ревью и обсуждение подходов к разработке.\n\n### Подходы к разработке с соглашениями\nИнтуитивно любые обсуждения к тому как работаем, будут вестись везде, где это только возможно, что ок, но постепенно будет накапливаться ощущение бесполезности усилий. Конструктивнее подталкивать коллег все фиксировать в некий единый источник истины - возник дискомфорт в работе? Что-то не нравится? Оформи минимально proposal в документ с соглашениями, мы его там на месте обсудим и примем. Сам процесс выслушивания, фиксации и принятия очень стимулирует того, кто столкнулся с чем-то в работе. Это критично важно.\n\nЯ предлагаю почаще подталкивать окружающих к тому, чтобы все мысли, идеи и проблемы максимально фиксировались. Нельзя допускать того, чтобы команда постоянно тонула в ощущении безысходности и существовала в страхе конфликта. Когда правила изложены в документе, то они обезличены, а значит можно оспаривать и предлагать что-то еще, без страха столкнуться с тем, что это адресно заденет и будет воспринято как что-то личное. Сравните с кейсом, когда в процессе код-ревью вам пишут `переименуй переменную, мы пишем в camelCase` VS `Мы пишем в camelCase [ссылка на правило]`. Точно также это касается и обсуждений в slack, если вы будете использовать документ как медиатор, то это снизит градус накала и позволит выстроить конструктивный диалог.\n\n### Код-ревью с соглашениями\nИзначально документ проектировался как гайд к код-ревью и решал проблему конфликтов в обсуждениях PR. Все соглашения можно разделить на те, которые можно автоматизировать и те, которые мы должны проверять об человека. \n\nДля начала стоит в целом определиться какую роль в вашем проекте играет код-ревью и зачем оно вам. Потом можно собрать основные замечания которые вы там встречаете и выписать их в этом документе. \n\nЯ предлагаю кидать ссылку при ревью на доку в ситуациях типовых проблем. Если кто-то не согласен с этим подходом, то в рамках задачи делает в соотв. с документом, но дальше предлагает изменить документ.\n\n### Онбоардинг с соглашениями\nЕсли вы часто нанимаете и типовым образом погружаете людей в проект, то гайд со схожей структурой у вас образуется сам собой. Я рекомендую исходить из объяснения того, как решается несколько типовых задач. А также дополнительно показать как именно эти соглашения можно менять, можно вовлечь на частном примере или показать историю изменений файла/обсуждения. Уверяю, что это сыграет очень сильную роль в будущем новичка в вашем проекте.\n\nВ дальнейшем, первые недели данный документ станет частым местом для CTRL+F новичка в вашем проекте. По моим наблюдениям погружение можно снизить с 2-4 недель до нескольких дней благодаря такому документу (или иному единственному источнику истинны).\n\n# Пример соглашений\nЯ распишу несколько разделов для ознакомления, оставляя все в виде списков без детализации. \n\n## Структура\nСамый сложный раздел, для каждого проекта полностью специфичен.\n\nЕсли у вас новый проект на реакте возьмите и сошлитесь здесь на [FSD](https://github.com/feature-sliced/documentation), если angular то строго используйте [официальные](https://angular.io/guide/file-structure) [гайдлайны](https://angular.io/guide/architecture).\n\nЕсли старый проект, то приложите сюда [граф импортов проекта](https://github.com/pahen/madge). Опишите типовые элементы системы, напр. компоненты/страницы/сервисы и для каждого опишите зачем он нужен, как устроен. Опишите структуру директорий. Это минимально.\n\n### Материалы \n- https://feature-sliced.design/\n- https://ru.hexlet.io/courses/js-frontend-architecture\n- https://www.youtube.com/watch?v=VegNqfiS6k8\n\n### Правила\n- Все вне директории legacy должно полностью следовать FSD \n- Файлы и директории строго именуем в snake_case\n- Любые helpers / utils файлы вне common запрещены\n\n### Рецепты\n- Как создать типовой UI компонент\n- Добавляем новую страницу\n- Как сделать свой хук\n\n## Зависимости\n### Рецепты\n- Как добавить новый пакет\n- Изменение размера бандла, как оценить с новой зависимостью\n\n### Правила\n- Добавление новой зависимости вместе с продуктовым PR запрещено, добавляем отдельным предварительным PR и согласуем с лидом\n- Добавление depricated авторами зависимостей запрещено\n- Запрещено добавлять дублирующие зависимости\n- Новый пакет обязательно должен поставляться в виде es module\n\n## Компоненты\nПри написании react-компонентов мы предпочитаем писать компоненты с помощью функций, а для вынесения частей бизнес кода хуки или чистые функции. \n\n### Материалы\n- https://ru.reactjs.org/docs/hooks-intro.html\n- https://jaketrent.com/post/naming-event-handlers-react\n\n### Рецепты\n- Пишем сториз для сторибука\n- Разметка для трекеров. Аналитика\n- Экспорт иконок из Figma\n- Добавляем растровые картинки\n- Замеряем ререндеры компонента\n\n### Правила\n- Любой новый UI компонент должен содержать сториз\n- Запрещен закомментированный код\n- Запрещены console.log или любой код для отладки\n- Работа с асинхронными операциями используем только async/await\n- Распаралеливаем запросы там где это возможно\n- Код, кроме реекспорта, в index.ts файлах запрещен\n- Запрещено передавать неиспользуемые пропсы\n- Запрещены default экспорты\n- Бразуерное апи должно вызываться только внутри useLayoutEffect\n- Правила eslint запрещено отключать\n\n## Стили\nМы используем css-modules всегда, глобальные стили запрещены. Используем общие миксины там где это возможно. Мы используем CSS Custom Properties, а все доступные переменные с дизайн-токенами можно посмотреть в локально развернутом сторибуке. Эти переменные доступны глобально: для их использования не нужно ничего импортировать.\n\n### Материалы\n- https://andrew-r.ru/notes/bem-vs-css-modules/\n- https://ru.bem.info/methodology/css/\n- https://css-tricks.com/the-shapes-of-css/\n- https://alligator.io/css/currentcolor/\n- https://ishadeed.com/article/css-color/\n\n### Рецепты\n- Какие миксины у нас есть и как их используем\n- Добавляем новый миксин\n\n### Правила\n- Разрешен только один файл стилей на директорию\n- Запрещена адаптивность посредством media запросов (используем js вместо этого)\n- Везде где можно используем дизайн токены\n- Корневой элемент всегда именуем root\n- Глобальные стили строго запрещены\n- Используем currentColor для цвета svg иконок\n- Правила stylelint запрещено отключать\n\n## Работа с данными\nИспользуем redux в связке с redux-toolkit. Само хранилище описано и собирается в /store нашего проекта, есть “общая часть” в /store /general. Бизнес части описываются в слайсах в рамках фич. Общая часть строго не зависит от слайсов.\n\n### Рецепты\n- Как добавить новый слайс\n\n### Правила\n- перед инициализация нужно обязательно ресетить стейт\n- импортировать хранилище разрешено только в страницах и фичах\n\n## Сеть\nСервис - абстракция для работы с данными. Сервисы могут работать с аналитикой, нашим api или предоставлять интерфейс доступа к иным данным (например маппинг роутинга).\n\nСервис состоит из файла с методами (имя сервиса) и адаптера. Адаптер содержит в себе методы преобразования полученных данных, его наличие обязательно если вы собираетесь как-то изменить полученные с сервера данные перед тем как разместить их в нашем сторе.\n\nДля сервиса который работает с сетью также обязательно наличие мок реализации, это необходимо для корректной работы блоков в сторибуке.\n\n### Рецепты\n- Разработка сервиса\n- Реализуем мок\n\n### Правила\n- Адаптер imgproxy обязателен если в ответе есть url графики\n- Наличие мок реализации обязательно\n\n## Обработка ошибок\n### Рецепты\n- Правильно реагируем на сетевые ошибки в интерфейсе\n\n### Правила\n- Запрещено заглушать ошибки, интерфейс должен реагировать на них\n- Наличие непредсказуемых ошибок в консоли запрещено\n\n## Доступы\n### Рецепты\n- Как ограничить доступ к роуту\n- Скрываем виджет или блок в зависимости от ролей\n- Добавляем новую роль пользователя\n- Как посмотреть страницу с другим набором ролей\n\n### Правила\n- При работе с ролями используем только хук usePermission, напрямую обрабатывать обьект пользователь запрещено\n\n## Дебаг\n### Рецепты\n- Как смотреть ошибки в sentry\n- Как смотреть логи\n- Где смотрим графики и что они значат\n- Деплой хотфикса\n\n## Секреты\n### Рецепты\n- Добавляем новый секрет\n\n### Правила\n- Все секреты должны быть в vault\n\n## Тенанты\n### Рецепты\n- Какой бывает специфика в разных деплоях\n- Брендируем стили\n- Добавляем специфичный виджет в тенант\n\n## I18N\nУ нас нет локализаций. Тексты размещаются inline.\n\n### Правила\n- в UI компонентах строки запрещены, все текста передаются пропсами\n\n## A11Y\nМы стремимся делать интерфейс доступным. A11y. Цели покрывать весь интерфейс доступностью - нет, но базовые вещи уже нужно начинать делать. Например следует использовать семантические HTML-элементы там, где возможно.\n### Материалы по теме\n- https://www.sberbank.ru/ru/person/specialbank/digitalguide\n- https://a11yproject.com/\n- https://a11y-style-guide.com/style-guide/\n- https://www.sarasoueidan.com/blog/keyboard-friendlier-article-listings/\n- https://www.youtube.com/watch?v=KAK-WAb9vow\n- https://www.24a11y.com/2018/accessible-svg-icons-with-inline-sprites/\n- https://www.w3schools.com/html/html5_semantic_elements.asp\n- https://www.freecodecamp.org/news/semantic-html5-elements/\n- https://cloudfour.com/thinks/autofill-what-web-devs-should-know-but-dont/\n- https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete\n\n### Рецепты\n- Как кастомный компонент сделать на базе нативного аналога\n- Как сделать доступную модалку\n\n### Правила\n- aria-label, aria-disabled и tabIndex должны быть размещены по возможности везде где это требуется\n- Inline-компоненты (ссылки, лейблы, ...) не должны иметь размер шрифта\n- Интерактивные компоненты (инпуты, кнопки, ...) должны иметь стили для :hover, :active, :focus и :disabled\n- Интерактивные компоненты (инпуты, кнопки, ...) должны иметь обводку при :focus\n- Интерактивные компоненты (инпуты, кнопки, ...) должны иметь cursor: pointer по умолчанию и cursor: defaultв состоянии :disabled.\n- SVG-иконки должны быть доступными\n- Для подтверждения формы использовать событие onSubmit, для отмены/очистки - использовать событие onReset\n- Используем по возможности autoFocus\n- Блокируем фокус в рамках модальных окон\n- Для кнопок используем \u003cbutton\u003e, для ссылок \u003ca\u003e\n\n## SEO\n### Материалы\n- https://habr.com/en/post/282880/\n\n### Рецепты\n- Прогононяем демостенд в lighthouse\n\n### Правила\n- Внешние ссылки обязаны содержать `rel=\"noopener noreferrer\"`\n\n## A/B-тестирование и feature-флаги\nДля раскатки функционала для части пользователей у нас есть два механизма: фичефлаги и AB-тесты.\n  \nПримерное правило для выбора между ними: если есть АБ-тест, то разработку следует делать через него. Если АБ- теста нет или он закончился – фичефлаг.\n\nПри этом обычно AB-тесты – инструмент аналитиков и продакт-менеджеров/продакт-овнеров, и инициатива разработки через AB-тестирование исходит от них. Фичефлаги используются, например, если требуется выкатить какой-нибудь функционал (или часть функционала) на прод, но чтоб у пользователей не было к нему доступа, или для постепенной выкатки функционала после завершения АБ-теста.\n  \n### Материалы\n- https://habr.com/en/post/282880/\n\n### Рецепты\n- Разработка с использованием эксперимента\n- Заводим флаг в flipper\n\n### Правила\n- Фичефлаг должен иметь префикс вида tckt-XXXX-* и ссылаться на конкретный тикет в jira описывающий поведение флага\n\n## Автотестирование\n### Рецепты\n- Добавляем data-qa-id\n- Пишем e2e тест\n- Пишем unit тест\n- Новый скриншотный тест\n- Обновляем скриншотные тесты\n\n### Правила\n- Если обновлены UI компоненты обязательно обновляем сторишоты\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcversus%2Fconventions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdcversus%2Fconventions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcversus%2Fconventions/lists"}