diff --git a/src/ru/yagamiproject/AndroidManifest.xml b/src/ru/yagamiproject/AndroidManifest.xml
new file mode 100644
index 000000000..30deb7f79
--- /dev/null
+++ b/src/ru/yagamiproject/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="eu.kanade.tachiyomi.extension" />
diff --git a/src/ru/yagamiproject/build.gradle b/src/ru/yagamiproject/build.gradle
new file mode 100644
index 000000000..2d10e3b4b
--- /dev/null
+++ b/src/ru/yagamiproject/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+    extName = 'YagamiProject'
+    pkgNameSuffix = 'ru.yagamiproject'
+    extClass = '.YagamiProject'
+    extVersionCode = 1
+    libVersion = '1.2'
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/ru/yagamiproject/res/mipmap-hdpi/ic_launcher.png b/src/ru/yagamiproject/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..4ff6956d7
Binary files /dev/null and b/src/ru/yagamiproject/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/ru/yagamiproject/res/mipmap-mdpi/ic_launcher.png b/src/ru/yagamiproject/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..90aa4a2c6
Binary files /dev/null and b/src/ru/yagamiproject/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/ru/yagamiproject/res/mipmap-xhdpi/ic_launcher.png b/src/ru/yagamiproject/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..931ea9a80
Binary files /dev/null and b/src/ru/yagamiproject/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/ru/yagamiproject/res/mipmap-xxhdpi/ic_launcher.png b/src/ru/yagamiproject/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..11bdce0cc
Binary files /dev/null and b/src/ru/yagamiproject/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/ru/yagamiproject/res/mipmap-xxxhdpi/ic_launcher.png b/src/ru/yagamiproject/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..9c6de3b7d
Binary files /dev/null and b/src/ru/yagamiproject/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/ru/yagamiproject/res/web_hi_res_512.png b/src/ru/yagamiproject/res/web_hi_res_512.png
new file mode 100644
index 000000000..34809a3f9
Binary files /dev/null and b/src/ru/yagamiproject/res/web_hi_res_512.png differ
diff --git a/src/ru/yagamiproject/src/eu/kanade/tachiyomi/extension/ru/mangabook/YagamiProject.kt b/src/ru/yagamiproject/src/eu/kanade/tachiyomi/extension/ru/mangabook/YagamiProject.kt
new file mode 100644
index 000000000..326cd22b2
--- /dev/null
+++ b/src/ru/yagamiproject/src/eu/kanade/tachiyomi/extension/ru/mangabook/YagamiProject.kt
@@ -0,0 +1,215 @@
+package eu.kanade.tachiyomi.extension.ru.yagamiproject
+
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.source.model.Filter
+import eu.kanade.tachiyomi.source.model.FilterList
+import eu.kanade.tachiyomi.source.model.MangasPage
+import eu.kanade.tachiyomi.source.model.Page
+import eu.kanade.tachiyomi.source.model.SChapter
+import eu.kanade.tachiyomi.source.model.SManga
+import eu.kanade.tachiyomi.source.online.ParsedHttpSource
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.Headers
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+class YagamiProject : ParsedHttpSource() {
+    // Info
+    override val name = "YagamiProject"
+    override val baseUrl = "https://read.yagami.me"
+    override val lang = "ru"
+    override val supportsLatest = true
+    private val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
+    override fun headersBuilder(): Headers.Builder = Headers.Builder()
+        .add("User-Agent", userAgent)
+        .add("Referer", baseUrl)
+
+    // Popular
+    override fun popularMangaRequest(page: Int): Request =
+        GET("$baseUrl/list-new/$page", headers)
+    override fun popularMangaNextPageSelector() = ".panel_nav .button a"
+    override fun popularMangaSelector() = ".list .group"
+    override fun popularMangaFromElement(element: Element): SManga {
+        return SManga.create().apply {
+            element.select(".title a").first().let {
+                setUrlWithoutDomain(it.attr("href"))
+                title = it.attr("title").split(" / ").sorted().first()
+            }
+            thumbnail_url = element.select(".cover_mini > img").attr("src")
+        }
+    }
+
+    // Latest
+    override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/latest/$page", headers)
+    override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
+    override fun latestUpdatesSelector() = popularMangaSelector()
+    override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
+
+    // Search
+    override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+        val url = if (query.isNotBlank()) {
+            "$baseUrl/reader/search/?s=$query&p=$page"
+        } else {
+            (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
+                when (filter) {
+                    is CategoryList -> {
+                        if (filter.state > 0) {
+                            val CatQ = getCategoryList()[filter.state].name
+                            val catUrl = "$baseUrl/tags/$CatQ".toHttpUrlOrNull()!!.newBuilder()
+                            return GET(catUrl.toString(), headers)
+                        }
+                    }
+                    is FormatList -> {
+                        if (filter.state > 0) {
+                            val FormN = getFormatList()[filter.state].query
+                            val formaUrl = "$baseUrl/$FormN".toHttpUrlOrNull()!!.newBuilder()
+                            return GET(formaUrl.toString(), headers)
+                        }
+                    }
+                }
+            }
+            throw Exception("Filters Not")
+        }
+        return GET(url, headers)
+    }
+
+    override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
+    override fun searchMangaSelector(): String = popularMangaSelector()
+    override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
+    override fun searchMangaParse(response: Response): MangasPage {
+        return popularMangaParse(response)
+    }
+
+    // Details
+    override fun mangaDetailsParse(document: Document): SManga {
+        val infoElement = document.select(".large.comic .info").first()
+        val manga = SManga.create()
+        val titlestr = document.select("title").text().substringBefore(" :: Yagami").split(" :: ").sorted()
+        manga.title = titlestr.first().replace(":: ", "")
+        manga.thumbnail_url = document.select(".cover img").first().attr("src")
+        manga.author = infoElement.select("li:contains(Автор)").text().substringAfter("Автор(ы): ").split(" / ").sorted().first()
+        manga.status = when (infoElement.select("li:contains(Статус перевода) span").text()) {
+            "онгоинг" -> SManga.ONGOING
+            "активный" -> SManga.ONGOING
+            "завершён" -> SManga.COMPLETED
+            else -> SManga.UNKNOWN
+        }
+        manga.genre = infoElement.select("li:contains(Жанры)").text().substringAfter("Жанры: ")
+        val altSelector = infoElement.select("li:contains(Название)")
+        var altName = ""
+        if (altSelector.isNotEmpty()) {
+            altName = "Альтернативные названия:\n" + altSelector.toString().replace("<br>", " / ").substringAfter(" / ").substringBefore("</li>") + "\n\n"
+        }
+        manga.description = titlestr.last().replace(":: ", "") + "\n" + altName + infoElement.select("li:contains(Описание)").text().substringAfter("Описание: ")
+        return manga
+    }
+
+    // Chapters
+    override fun chapterListSelector(): String = ".list .element"
+    override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
+        val chapter = element.select(".title a")
+        val chapterScan_Date = element.select(".meta_r")
+        name = when {
+            chapter.attr("title").isNullOrBlank() -> chapter.text()
+            else -> chapter.attr("title")
+        }
+
+        chapter_number = when {
+            name.contains("Глава") -> name.substringAfter("Глава ").substringBefore(":").toFloat()
+            name.contains("Акт") -> name.substringAfter("Акт №").substringBefore(":").toFloat()
+            else -> 0F
+        }
+        setUrlWithoutDomain(chapter.attr("href"))
+        date_upload = parseDate(chapterScan_Date.text().substringAfter(", "))
+        scanlator = if (chapterScan_Date.select("a").isNotEmpty()) {
+            chapterScan_Date.select("a").map { it.text() }.joinToString(" / ")
+        } else null
+    }
+    private fun parseDate(date: String): Long {
+        return SimpleDateFormat("dd.MM.yyyy", Locale.US).parse(date)?.time ?: 0
+    }
+    // Pages
+    override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
+        val defaultsel = document.select(".dropdown li a")
+        val webtoonsel = document.select(".web_pictures img.web_img")
+
+        if (webtoonsel.isNullOrEmpty()) {
+            defaultsel.forEach {
+                add(Page(it.text().substringAfter("Стр. ").toInt(), it.attr("href")))
+            }
+        } else {
+            webtoonsel.mapIndexed { i, img ->
+                add(Page(i, "", img.attr("src")))
+            }
+        }
+    }
+    override fun imageUrlParse(response: Response): String = response.asJsoup().select("#page img").attr("src")
+    override fun imageUrlParse(document: Document): String = throw Exception("imageUrlParse(document: Document) Not Used")
+
+    // Filters
+
+    override fun getFilterList() = FilterList(
+        Filter.Header("ПРИМЕЧАНИЕ: Фильтры исключают другдруга!"),
+        CategoryList(categoriesName),
+        FormatList(formasName)
+    )
+
+    private class FormatList(formas: Array<String>) : Filter.Select<String>("Тип", formas)
+    private data class FormUnit(val name: String, val query: String)
+    private val formasName = getFormatList().map {
+        it.name
+    }.toTypedArray()
+
+    private fun getFormatList() = listOf(
+        FormUnit("Все", "not"),
+        FormUnit("Манга", "manga"),
+        FormUnit("Манхва", "manhva"),
+        FormUnit("Веб Манхва", "webtoon"),
+        FormUnit("Маньхуа", "manhua")
+    )
+
+    private class CategoryList(categories: Array<String>) : Filter.Select<String>("Категории", categories)
+    private data class CatUnit(val name: String)
+    private val categoriesName = getCategoryList().map {
+        it.name
+    }.toTypedArray()
+
+    private fun getCategoryList() = listOf(
+        CatUnit("Без категории"),
+        CatUnit("боевые искусства"),
+        CatUnit("гарем"),
+        CatUnit("гендерная интрига"),
+        CatUnit("дзёсэй"),
+        CatUnit("для взрослых"),
+        CatUnit("драма"),
+        CatUnit("зрелое"),
+        CatUnit("исторический"),
+        CatUnit("комедия"),
+        CatUnit("меха"),
+        CatUnit("мистика"),
+        CatUnit("научная фантастика"),
+        CatUnit("непристойности"),
+        CatUnit("постапокалиптика"),
+        CatUnit("повседневность"),
+        CatUnit("приключения"),
+        CatUnit("психология"),
+        CatUnit("романтика"),
+        CatUnit("сверхъестественное"),
+        CatUnit("сёдзё"),
+        CatUnit("сёнэн"),
+        CatUnit("спорт"),
+        CatUnit("сэйнэн"),
+        CatUnit("трагедия"),
+        CatUnit("ужасы"),
+        CatUnit("фэнтези"),
+        CatUnit("школьная жизнь"),
+        CatUnit("экшн"),
+        CatUnit("эротика"),
+        CatUnit("этти")
+    )
+}