diff --git a/assets.go b/assets.go
index b3ed90c1011a144565e9fc8f293473352ba6cba3..04eefe77f3c149c172a1f82c05428a1eadbb1eef 100644
--- a/assets.go
+++ b/assets.go
@@ -6,47 +6,42 @@ import (
 	"path/filepath"
 
 	"git.perx.ru/perxis/perxis-go/pkg/errors"
+	"git.perx.ru/perxis/perxis-go/yaml"
 	jsoniter "github.com/json-iterator/go"
-	"gopkg.in/yaml.v3"
 )
 
 // Assets предоставляет методы для загрузки данных из файловой системы
 type Assets[T any] struct {
+	FS          fs.FS
 	Constructor func() T
 }
 
 // NewAssets возвращает новый экземпляр загрузчика
-func NewAssets[T any]() *Assets[T] {
+func NewAssets[T any](fsys fs.FS) *Assets[T] {
 	return &Assets[T]{
-		Constructor: func() (t T) { return t },
+		FS:          fsys,
+		Constructor: func() (t T) { return t }, // По умолчанию zero-value
 	}
 }
 
-type FromFSFunc[T any] func(fsys fs.FS) ([]T, error)
-type FromFileFunc[T any] func(file fs.File) ([]T, error)
-
-func (a *Assets[T]) Funcs() (FromFSFunc[T], FromFileFunc[T]) {
-	return a.FromFS, a.FromFile
-}
-
 // WithConstructor устанавливает конструктор для создания новых экземпляров
 func (a *Assets[T]) WithConstructor(t func() T) *Assets[T] {
 	a.Constructor = t
 	return a
 }
 
-// MustFrom возвращает все записи в переданной файловой системе
-func (a *Assets[T]) MustFrom(fsys fs.FS, path string) []T {
-	res, err := a.From(fsys, path)
+// MustFrom возвращает все записи из переданного файла или директории
+func (a *Assets[T]) MustFrom(path string) []T {
+	res, err := a.From(path)
 	if err != nil {
 		panic(err)
 	}
 	return res
 }
 
-// MustOneFrom возвращает одну запись из переданного файла
-func (a *Assets[T]) MustOneFrom(fsys fs.FS, path string) T {
-	res, err := a.From(fsys, path)
+// MustOneFrom возвращает одну запись из переданного файла или директории
+func (a *Assets[T]) MustOneFrom(path string) T {
+	res, err := a.From(path)
 	if err != nil {
 		panic(err)
 	}
@@ -59,9 +54,9 @@ func (a *Assets[T]) MustOneFrom(fsys fs.FS, path string) T {
 	return res[0]
 }
 
-// From возвращает записи из переданного файла
-func (a *Assets[T]) From(fsys fs.FS, path string) ([]T, error) {
-	f, err := fsys.Open(path)
+// From возвращает записи из переданного файла или директории
+func (a *Assets[T]) From(path string) ([]T, error) {
+	f, err := a.FS.Open(path)
 	if err != nil {
 		return nil, err
 	}
@@ -74,13 +69,8 @@ func (a *Assets[T]) From(fsys fs.FS, path string) ([]T, error) {
 	}
 
 	if stat.IsDir() {
-		sub, err := fs.Sub(fsys, path)
-		if err != nil {
-			return nil, err
-		}
-		return a.FromFS(sub)
+		return a.FromDir(path)
 	}
-
 	return a.FromFile(f)
 }
 
@@ -107,10 +97,10 @@ func (a *Assets[T]) FromFile(file fs.File) ([]T, error) {
 	return nil, errors.Errorf("file '%s' must be in JSON or YAML format", stat.Name())
 }
 
-// FromFS возвращает все записи в переданной файловой системе
-func (a *Assets[T]) FromFS(fsys fs.FS) (result []T, err error) {
-	if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, _ error) error {
-		file, err := fsys.Open(path)
+// FromDir возвращает все записи из переданной папки рекурсивно
+func (a *Assets[T]) FromDir(dir string) (result []T, err error) {
+	if err := fs.WalkDir(a.FS, dir, func(path string, d fs.DirEntry, _ error) error {
+		file, err := a.FS.Open(path)
 		if err != nil {
 			return err
 		}
@@ -128,8 +118,8 @@ func (a *Assets[T]) FromFS(fsys fs.FS) (result []T, err error) {
 }
 
 // FromJSON возвращает запись из JSON
-func (c *Assets[T]) FromJSON(r io.Reader) (T, error) {
-	entry := c.Constructor()
+func (a *Assets[T]) FromJSON(r io.Reader) (T, error) {
+	entry := a.Constructor()
 	data, err := io.ReadAll(r)
 	if err != nil {
 		return entry, err
@@ -140,11 +130,11 @@ func (c *Assets[T]) FromJSON(r io.Reader) (T, error) {
 }
 
 // FromYAML возвращает записи из YAML
-func (c *Assets[T]) FromYAML(r io.Reader) (result []T, err error) {
+func (a *Assets[T]) FromYAML(r io.Reader) (result []T, err error) {
 	decoder := yaml.NewDecoder(r)
 	for {
 		var data interface{}
-		err = decoder.Decode(&data)
+		err = decoder.Decode(yaml.WithTagProcessor(a.FS)(&data))
 		if errors.Is(err, io.EOF) {
 			break
 		}
@@ -157,7 +147,7 @@ func (c *Assets[T]) FromYAML(r io.Reader) (result []T, err error) {
 			return nil, err
 		}
 
-		entry := c.Constructor()
+		entry := a.Constructor()
 		if err = jsoniter.Unmarshal(json, &entry); err != nil {
 			return nil, err
 		}
diff --git a/assets_test.go b/assets_test.go
index 69a71b8a5323ca6bd8d7b103f66a70b62054ef29..09c83ad02de471b558c9bc6d25298bdd43a5435f 100644
--- a/assets_test.go
+++ b/assets_test.go
@@ -26,7 +26,7 @@ type nested struct {
 	Option *bool
 }
 
-func TestFromFS(t *testing.T) {
+func TestFromDir(t *testing.T) {
 	tr := true
 	i1 := &testEntry{
 		ID:   "item1",
@@ -46,8 +46,8 @@ func TestFromFS(t *testing.T) {
 	i3 := *i1
 	i3.ID = "item3"
 
-	assets := NewAssets[*testEntry]()
-	r, err := assets.FromFS(os.DirFS("assets/tests/assets"))
+	assets := NewAssets[*testEntry](os.DirFS("."))
+	r, err := assets.FromDir("assets/tests/assets")
 	require.NoError(t, err)
 	require.Len(t, r, 3)
 	assert.ElementsMatch(t, []*testEntry{i1, &i2, &i3}, r)
@@ -73,13 +73,14 @@ func TestFrom(t *testing.T) {
 	i3 := *i1
 	i3.ID = "item3"
 
-	assets := NewAssets[*testEntry]()
-	r, err := assets.From(os.DirFS("assets"), "tests/assets")
+	assets := NewAssets[*testEntry](os.DirFS("."))
+	r, err := assets.From("assets/tests/assets")
 	require.NoError(t, err)
 	require.Len(t, r, 3)
 	assert.ElementsMatch(t, []*testEntry{i1, &i2, &i3}, r)
 
-	r, err = assets.From(os.DirFS("assets"), "tests/assets/items.yaml")
+	assets = NewAssets[*testEntry](os.DirFS("assets/tests"))
+	r, err = assets.From("assets/items.yaml")
 	require.NoError(t, err)
 	require.Len(t, r, 2)
 	assert.Equal(t, []*testEntry{i1, &i2}, r)
diff --git a/pkg/extension/extension.go b/pkg/extension/extension.go
index 15b92676be86b1782eb0ca8e5feb98bf1f8ba186..432078899448d7f4875991e06fba44dd17830917 100644
--- a/pkg/extension/extension.go
+++ b/pkg/extension/extension.go
@@ -2,6 +2,7 @@ package extension
 
 import (
 	"context"
+	"io/fs"
 
 	"go.uber.org/zap"
 
@@ -40,9 +41,6 @@ var (
 	ErrUninstall        = errors.New("uninstall failed")
 	ErrNotInstalled     = errors.New("not installed")
 	ErrUnknownExtension = errors.New("unknown extension")
-
-	ManifestAssets   = perxis.NewAssets[*ExtensionDescriptor]()
-	ManifestFromFile = ManifestAssets.MustOneFrom
 )
 
 // Runnable описывает интерфейс сервиса с запуском и остановкой. Вызывается сервером расширений
@@ -101,3 +99,8 @@ func UpdateExtensionCollections() setup.CollectionOption {
 		}
 	}
 }
+
+// LoadManifest загружает манифест из файла manifest.yaml
+func LoadManifest(fsys fs.FS) *ExtensionDescriptor {
+	return perxis.NewAssets[*ExtensionDescriptor](fsys).MustOneFrom("manifest.yml")
+}
diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go
index fdb402b412de15b3ba8aa9d2b0244ea3d22e8f09..7b337f8ab68f732fb3ab2ac804fe89e082c58c6a 100644
--- a/pkg/schema/schema.go
+++ b/pkg/schema/schema.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"reflect"
 
-	"git.perx.ru/perxis/perxis-go"
 	"git.perx.ru/perxis/perxis-go/pkg/errors"
 	"git.perx.ru/perxis/perxis-go/pkg/expr"
 	"git.perx.ru/perxis/perxis-go/pkg/schema/field"
@@ -34,10 +33,6 @@ var (
 	Modify   = modify.Modify
 	Validate = validate.Validate
 	Evaluate = field.Evaluate
-
-	Assets   = perxis.NewAssets[*Schema]().WithConstructor(func() *Schema { return New() })
-	FromFS   = Assets.FromFS
-	FromFile = Assets.FromFile
 )
 
 func (s *Schema) Clone(reset bool) *Schema {
diff --git a/pkg/schema/test/assets/invalid.json b/pkg/schema/test/assets/invalid.json
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/pkg/schema/test/assets/not_schema.txt b/pkg/schema/test/assets/not_schema.txt
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/pkg/schema/test/assets/web_pages.json b/pkg/schema/test/assets/web_pages.json
deleted file mode 100644
index 652753c911e79dca0896b2c57587400202d0da69..0000000000000000000000000000000000000000
--- a/pkg/schema/test/assets/web_pages.json
+++ /dev/null
@@ -1,420 +0,0 @@
-{
-    "ui": {
-        "widget": "Tabs",
-        "options": {
-            "description": "path",
-            "collection_icon": "ApartmentOutlined/FileTextOutlined",
-            "fields": [
-                "content",
-                "seo",
-                "settings",
-                "advanced",
-                "design",
-                "variables"
-            ],
-            "title": "name",
-            "key": "path"
-        },
-        "list_view": {
-            "options": {
-                "sort": [
-                    "path"
-                ],
-                "page_size": 50,
-                "fields": [
-                    "path",
-                    "name",
-                    "updated_at",
-                    "updated_by",
-                    "state"
-                ]
-            }
-        }
-    },
-    "includes": [
-        {
-            "ref": "hoop_item_options",
-            "optional": true
-        },
-        {
-            "ref": "ext_web_pages_*",
-            "optional": true
-        }
-    ],
-    "type": "object",
-    "params": {
-        "inline": false,
-        "fields": {
-            "design": {
-                "title": "Дизайн",
-                "includes": [
-                    {
-                        "ref": "web_design"
-                    }
-                ],
-                "type": "object",
-                "params": {
-                    "inline": false,
-                    "fields": {}
-                }
-            },
-            "variables": {
-                "title": "Переменные",
-                "ui": {
-                    "options": {
-                        "fields": [
-                            "variables"
-                        ]
-                    }
-                },
-                "type": "object",
-                "params": {
-                    "inline": true,
-                    "fields": {
-                        "variables": {
-                            "type": "array",
-                            "params": {
-                                "item": {
-                                    "ui": {
-                                        "options": {
-                                            "collection_icon": "SettingOutlined/FileExcelOutlined",
-                                            "fields": [
-                                                "id",
-                                                "name",
-                                                "value"
-                                            ]
-                                        },
-                                        "list_view": {
-                                            "options": {
-                                                "fields": [
-                                                    "id",
-                                                    "name",
-                                                    "updated_at",
-                                                    "updated_by",
-                                                    "state"
-                                                ],
-                                                "page_size": 50
-                                            }
-                                        }
-                                    },
-                                    "type": "object",
-                                    "params": {
-                                        "inline": false,
-                                        "fields": {
-                                            "id": {
-                                                "title": "Идентификатор переменной",
-                                                "text_search": true,
-                                                "options": {
-                                                    "required": true
-                                                },
-                                                "type": "string",
-                                                "params": {}
-                                            },
-                                            "name": {
-                                                "title": "Название переменной",
-                                                "text_search": true,
-                                                "type": "string",
-                                                "params": {}
-                                            },
-                                            "value": {
-                                                "title": "Значение переменной",
-                                                "type": "string",
-                                                "params": {}
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            },
-            "content": {
-                "title": "Содержимое страницы",
-                "ui": {
-                    "options": {
-                        "fields": [
-                            "blocks"
-                        ]
-                    }
-                },
-                "type": "object",
-                "params": {
-                    "inline": true,
-                    "fields": {
-                        "blocks": {
-                            "title": "Блоки",
-                            "ui": {
-                                "widget": "BlockList",
-                                "options": {
-                                    "create": {
-                                        "classes": [
-                                            "class_web_blocks"
-                                        ]
-                                    }
-                                }
-                            },
-                            "type": "array",
-                            "params": {
-                                "item": {
-                                    "title": "Блок",
-                                    "type": "reference",
-                                    "params": {
-                                        "allowedCollections": [
-                                            "web_block_*"
-                                        ]
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            },
-            "seo": {
-                "title": "SEO",
-                "includes": [
-                    {
-                        "ref": "web_seo"
-                    }
-                ],
-                "type": "object",
-                "params": {
-                    "inline": false,
-                    "fields": {}
-                }
-            },
-            "settings": {
-                "title": "Настройки",
-                "ui": {
-                    "options": {
-                        "fields": [
-                            "name",
-                            "parent",
-                            "path",
-                            "slug",
-                            "section",
-                            "datasource",
-                            "redirect",
-                            "redirect_path",
-                            "redirect_url",
-                            "outputs",
-                            "navTitle",
-                            "navHide",
-                            "weight"
-                        ]
-                    }
-                },
-                "type": "object",
-                "params": {
-                    "inline": true,
-                    "fields": {
-                        "path": {
-                            "title": "Путь",
-                            "unique": true,
-                            "text_search": true,
-                            "options": {
-                                "value": "$perxis.Item.Template == true ? _value : parent == nil ?  '/' : slug == nil ? make_path(parent, slugify(replace_markers(name))) : make_path(parent, slugify(replace_markers(slug)))"
-                            },
-                            "type": "string",
-                            "params": {}
-                        },
-                        "redirect_url": {
-                            "title": "URL для перехода",
-                            "condition": "redirect == true",
-                            "type": "string",
-                            "params": {}
-                        },
-                        "outputs": {
-                            "title": "Форматы страницы для вывода",
-                            "type": "array",
-                            "params": {
-                                "item": {
-                                    "ui": {
-                                        "widget": "Lookup",
-                                        "options": {
-                                            "allowedCollections": [
-                                                {
-                                                    "collection": "web_outputs"
-                                                }
-                                            ]
-                                        }
-                                    },
-                                    "type": "string",
-                                    "params": {}
-                                }
-                            }
-                        },
-                        "weight": {
-                            "title": "Порядок следования",
-                            "ui": {
-                                "widget": "NumberInput"
-                            },
-                            "type": "number",
-                            "params": {
-                                "format": "int"
-                            }
-                        },
-                        "navHide": {
-                            "title": "Скрыть страницу из навигации",
-                            "ui": {
-                                "widget": "Checkbox"
-                            },
-                            "type": "bool",
-                            "params": {}
-                        },
-                        "section": {
-                            "title": "Раздел",
-                            "ui": {
-                                "widget": "Checkbox"
-                            },
-                            "type": "bool",
-                            "params": {}
-                        },
-                        "parent": {
-                            "title": "Родительский раздел",
-                            "description": "Раздел сайта, где расположена страница",
-                            "ui": {
-                                "widget": "Lookup",
-                                "options": {
-                                    "allowedCollections": [
-                                        {
-                                            "collection": "web_pages"
-                                        }
-                                    ]
-                                }
-                            },
-                            "type": "string",
-                            "params": {}
-                        },
-                        "name": {
-                            "title": "Название",
-                            "indexed": true,
-                            "text_search": true,
-                            "options": {
-                                "required": true,
-                                "value": "$perxis.Item.Template == true ? _value : replace_markers(_value)"
-                            },
-                            "type": "string",
-                            "params": {}
-                        },
-                        "navTitle": {
-                            "title": "Название для навигации",
-                            "type": "string",
-                            "params": {}
-                        },
-                        "redirect_path": {
-                            "title": "Страница для перехода",
-                            "ui": {
-                                "widget": "Lookup",
-                                "options": {
-                                    "allowedCollections": [
-                                        {
-                                            "collection": "web_pages"
-                                        }
-                                    ]
-                                }
-                            },
-                            "condition": "redirect == true",
-                            "type": "string",
-                            "params": {}
-                        },
-                        "datasource": {
-                            "title": "Источник данных",
-                            "description": "Источник данных из которого будут формироваться подстраницы раздела",
-                            "ui": {
-                                "widget": "Lookup",
-                                "options": {
-                                    "allowedCollections": [
-                                        {
-                                            "collection": "web_datasources"
-                                        }
-                                    ]
-                                }
-                            },
-                            "condition": "section == true",
-                            "type": "string",
-                            "params": {}
-                        },
-                        "redirect": {
-                            "title": "Перенаправление",
-                            "description": "Страница не имеет содержимого и перенаправляет посетителей на другой адрес",
-                            "ui": {
-                                "widget": "Checkbox"
-                            },
-                            "type": "bool",
-                            "params": {}
-                        },
-                        "slug": {
-                            "title": "Slug",
-                            "description": "Идентификатор страницы в адресе URL",
-                            "text_search": true,
-                            "options": {
-                                "value": "$perxis.Item.Template == true ? _value : parent == nil ? nil : _value == nil ?  slugify(replace_markers(name)) :  slugify(replace_markers(_value))"
-                            },
-                            "type": "string",
-                            "params": {}
-                        }
-                    }
-                }
-            },
-            "advanced": {
-                "title": "Расширенные настройки",
-                "ui": {
-                    "options": {
-                        "fields": [
-                            "scripts"
-                        ]
-                    }
-                },
-                "type": "object",
-                "params": {
-                    "inline": false,
-                    "fields": {
-                        "scripts": {
-                            "title": "Дополнительные скрипты",
-                            "type": "array",
-                            "params": {
-                                "item": {
-                                    "ui": {
-                                        "options": {
-                                            "fields": [
-                                                "src",
-                                                "type",
-                                                "content"
-                                            ]
-                                        }
-                                    },
-                                    "type": "object",
-                                    "params": {
-                                        "inline": false,
-                                        "fields": {
-                                            "type": {
-                                                "title": "Media Type скрипта",
-                                                "type": "string",
-                                                "params": {}
-                                            },
-                                            "content": {
-                                                "title": "Содержимое скрипта",
-                                                "type": "string",
-                                                "params": {}
-                                            },
-                                            "src": {
-                                                "title": "URL для загрузки скрипта",
-                                                "type": "string",
-                                                "params": {}
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    },
-    "loaded": false,
-    "metadata": {
-        "extension": "perxisweb"
-    }
-}
\ No newline at end of file
diff --git a/pkg/schema/test/assets/web_pages.yml b/pkg/schema/test/assets/web_pages.yml
deleted file mode 100644
index 7fdfdd24fa9dcaa04d31ca1506955c86d6e3ce43..0000000000000000000000000000000000000000
--- a/pkg/schema/test/assets/web_pages.yml
+++ /dev/null
@@ -1,297 +0,0 @@
----
-ui:
-  widget: Tabs
-  options:
-    description: path
-    collection_icon: ApartmentOutlined/FileTextOutlined
-    fields:
-    - content
-    - seo
-    - settings
-    - advanced
-    - design
-    - variables
-    title: name
-    key: path
-  list_view:
-    options:
-      sort:
-      - path
-      page_size: 50
-      fields:
-      - path
-      - name
-      - updated_at
-      - updated_by
-      - state
-includes:
-- ref: hoop_item_options
-  optional: true
-- ref: ext_web_pages_*
-  optional: true
-type: object
-params:
-  inline: false
-  fields:
-    design:
-      title: Дизайн
-      includes:
-      - ref: web_design
-      type: object
-      params:
-        inline: false
-        fields: {}
-    variables:
-      title: Переменные
-      ui:
-        options:
-          fields:
-          - variables
-      type: object
-      params:
-        inline: true
-        fields:
-          variables:
-            type: array
-            params:
-              item:
-                ui:
-                  options:
-                    collection_icon: SettingOutlined/FileExcelOutlined
-                    fields:
-                    - id
-                    - name
-                    - value
-                  list_view:
-                    options:
-                      fields:
-                      - id
-                      - name
-                      - updated_at
-                      - updated_by
-                      - state
-                      page_size: 50
-                type: object
-                params:
-                  inline: false
-                  fields:
-                    id:
-                      title: Идентификатор переменной
-                      text_search: true
-                      options:
-                        required: true
-                      type: string
-                      params: {}
-                    name:
-                      title: Название переменной
-                      text_search: true
-                      type: string
-                      params: {}
-                    value:
-                      title: Значение переменной
-                      type: string
-                      params: {}
-    content:
-      title: Содержимое страницы
-      ui:
-        options:
-          fields:
-          - blocks
-      type: object
-      params:
-        inline: true
-        fields:
-          blocks:
-            title: Блоки
-            ui:
-              widget: BlockList
-              options:
-                create:
-                  classes:
-                  - class_web_blocks
-            type: array
-            params:
-              item:
-                title: Блок
-                type: reference
-                params:
-                  allowedCollections:
-                  - web_block_*
-    seo:
-      title: SEO
-      includes:
-      - ref: web_seo
-      type: object
-      params:
-        inline: false
-        fields: {}
-    settings:
-      title: Настройки
-      ui:
-        options:
-          fields:
-          - name
-          - parent
-          - path
-          - slug
-          - section
-          - datasource
-          - redirect
-          - redirect_path
-          - redirect_url
-          - outputs
-          - navTitle
-          - navHide
-          - weight
-      type: object
-      params:
-        inline: true
-        fields:
-          path:
-            title: Путь
-            unique: true
-            text_search: true
-            options:
-              value: "$perxis.Item.Template == true ? _value : parent == nil ?  '/'
-                : slug == nil ? make_path(parent, slugify(replace_markers(name)))
-                : make_path(parent, slugify(replace_markers(slug)))"
-            type: string
-            params: {}
-          redirect_url:
-            title: URL для перехода
-            condition: redirect == true
-            type: string
-            params: {}
-          outputs:
-            title: Форматы страницы для вывода
-            type: array
-            params:
-              item:
-                ui:
-                  widget: Lookup
-                  options:
-                    allowedCollections:
-                    - collection: web_outputs
-                type: string
-                params: {}
-          weight:
-            title: Порядок следования
-            ui:
-              widget: NumberInput
-            type: number
-            params:
-              format: int
-          navHide:
-            title: Скрыть страницу из навигации
-            ui:
-              widget: Checkbox
-            type: bool
-            params: {}
-          section:
-            title: Раздел
-            ui:
-              widget: Checkbox
-            type: bool
-            params: {}
-          parent:
-            title: Родительский раздел
-            description: Раздел сайта, где расположена страница
-            ui:
-              widget: Lookup
-              options:
-                allowedCollections:
-                - collection: web_pages
-            type: string
-            params: {}
-          name:
-            title: Название
-            indexed: true
-            text_search: true
-            options:
-              required: true
-              value: "$perxis.Item.Template == true ? _value : replace_markers(_value)"
-            type: string
-            params: {}
-          navTitle:
-            title: Название для навигации
-            type: string
-            params: {}
-          redirect_path:
-            title: Страница для перехода
-            ui:
-              widget: Lookup
-              options:
-                allowedCollections:
-                - collection: web_pages
-            condition: redirect == true
-            type: string
-            params: {}
-          datasource:
-            title: Источник данных
-            description: Источник данных из которого будут формироваться подстраницы
-              раздела
-            ui:
-              widget: Lookup
-              options:
-                allowedCollections:
-                - collection: web_datasources
-            condition: section == true
-            type: string
-            params: {}
-          redirect:
-            title: Перенаправление
-            description: Страница не имеет содержимого и перенаправляет посетителей
-              на другой адрес
-            ui:
-              widget: Checkbox
-            type: bool
-            params: {}
-          slug:
-            title: Slug
-            description: Идентификатор страницы в адресе URL
-            text_search: true
-            options:
-              value: "$perxis.Item.Template == true ? _value : parent == nil ? nil
-                : _value == nil ?  slugify(replace_markers(name)) :  slugify(replace_markers(_value))"
-            type: string
-            params: {}
-    advanced:
-      title: Расширенные настройки
-      ui:
-        options:
-          fields:
-          - scripts
-      type: object
-      params:
-        inline: false
-        fields:
-          scripts:
-            title: Дополнительные скрипты
-            type: array
-            params:
-              item:
-                ui:
-                  options:
-                    fields:
-                    - src
-                    - type
-                    - content
-                type: object
-                params:
-                  inline: false
-                  fields:
-                    type:
-                      title: Media Type скрипта
-                      type: string
-                      params: {}
-                    content:
-                      title: Содержимое скрипта
-                      type: string
-                      params: {}
-                    src:
-                      title: URL для загрузки скрипта
-                      type: string
-                      params: {}
-loaded: false
-metadata:
-  extension: perxisweb
diff --git a/pkg/schema/test/convert_test.go b/pkg/schema/test/convert_test.go
deleted file mode 100644
index 5e791570ebfc12c9efc9a4c9295ce5dacced4af5..0000000000000000000000000000000000000000
--- a/pkg/schema/test/convert_test.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package test
-
-import (
-	"os"
-	"testing"
-
-	"git.perx.ru/perxis/perxis-go/pkg/extension"
-	"git.perx.ru/perxis/perxis-go/pkg/references"
-	"git.perx.ru/perxis/perxis-go/pkg/schema"
-	"git.perx.ru/perxis/perxis-go/pkg/schema/field"
-	"git.perx.ru/perxis/perxis-go/pkg/schema/modify"
-	"git.perx.ru/perxis/perxis-go/pkg/schema/validate"
-	"github.com/stretchr/testify/require"
-)
-
-func TestFromFiles(t *testing.T) {
-	t.Run("Non-existen path", func(t *testing.T) {
-		schemas, err := schema.FromFS(os.DirFS("non-existen"))
-		require.Error(t, err)
-		require.ErrorContains(t, err, "no such file or directory")
-		require.Nil(t, schemas)
-	})
-
-	t.Run("Success", func(t *testing.T) {
-		schemas, err := schema.FromFS(os.DirFS("assets"))
-		for _, s := range schemas {
-			s.ClearState()
-		}
-		require.NoError(t, err)
-		require.Len(t, schemas, 2, "В директории хранятся две корректные схемы")
-		require.ElementsMatch(t, []*schema.Schema{getPagesSchema(), getPagesSchema()}, schemas, "Cхемы должны соответствовать объекту из функции")
-	})
-}
-
-// Оригинальное объявление схемы Web/Страницы
-// Значение констант подставлено вручную
-func getPagesSchema() *schema.Schema {
-	content := field.Object(
-		true, "blocks", field.Array(
-			references.Field([]string{"web_block_*"}).SetTitle("Блок"),
-		).
-			SetTitle("Блоки").
-			WithUI(&field.UI{
-				Widget: "BlockList",
-				Options: map[string]interface{}{
-					"create": map[string]interface{}{
-						"classes": []string{"class_web_blocks"},
-					},
-				},
-			}),
-	).SetTitle("Содержимое страницы")
-
-	// SEO
-	seo := field.Object().WithIncludes("web_seo").SetTitle("SEO")
-
-	//Settings
-	settings := field.Object(true,
-		"name", field.String(
-			validate.Required(),
-			modify.Value("$perxis.Item.Template == true ? _value : replace_markers(_value)"),
-		).SetTitle("Название").SetTextSearch(true).SetIndexed(true),
-		"parent", field.String().SetTitle("Родительский раздел").SetDescription("Раздел сайта, где расположена страница").WithUI(&field.UI{
-			Widget: "Lookup",
-			Options: map[string]interface{}{
-				"allowedCollections": []interface{}{
-					map[string]interface{}{"collection": "web_pages"},
-				},
-			},
-		}), // TODO lookup "section == true"
-		"path", field.String(
-			modify.Value("$perxis.Item.Template == true ? _value : parent == nil ?  '/' : slug == nil ? make_path(parent, slugify(replace_markers(name))) : make_path(parent, slugify(replace_markers(slug)))"),
-		).SetTitle("Путь").SetUnique(true).SetTextSearch(true), // TODO readonly
-		"slug", field.String(modify.Value("$perxis.Item.Template == true ? _value : parent == nil ? nil : _value == nil ?  slugify(replace_markers(name)) :  slugify(replace_markers(_value))")).SetTitle("Slug").SetDescription("Идентификатор страницы в адресе URL").SetTextSearch(true),
-		"section", field.Bool().SetTitle("Раздел").WithUI(&field.UI{Widget: "Checkbox"}),
-		"datasource", field.String().WithUI(&field.UI{
-			Widget: "Lookup",
-			Options: map[string]interface{}{
-				"allowedCollections": []interface{}{
-					map[string]interface{}{"collection": "web_datasources"},
-				},
-			},
-		}).SetTitle("Источник данных").SetDescription("Источник данных из которого будут формироваться подстраницы раздела").SetCondition("section == true"),
-		"redirect", field.Bool().SetTitle("Перенаправление").SetDescription("Страница не имеет содержимого и перенаправляет посетителей на другой адрес").WithUI(&field.UI{Widget: "Checkbox"}),
-		"redirect_path", field.String().SetTitle("Страница для перехода").WithUI(&field.UI{
-			Widget: "Lookup",
-			Options: map[string]interface{}{
-				"allowedCollections": []interface{}{
-					map[string]interface{}{"collection": "web_pages"},
-				},
-			},
-		}).SetCondition("redirect == true"),
-		"redirect_url", field.String().SetTitle("URL для перехода").SetCondition("redirect == true"),
-		"outputs", field.Array(field.String().WithUI(&field.UI{
-			Widget: "Lookup",
-			Options: map[string]interface{}{
-				"allowedCollections": []interface{}{
-					map[string]interface{}{"collection": "web_outputs"},
-				},
-			},
-		})).SetTitle("Форматы страницы для вывода"),
-		"navTitle", field.String().SetTitle("Название для навигации"),
-		"navHide", field.Bool().SetTitle("Скрыть страницу из навигации").WithUI(&field.UI{Widget: "Checkbox"}),
-		"weight", field.Number(field.NumberFormatInt).SetTitle("Порядок следования").WithUI(&field.UI{Widget: "NumberInput"}),
-	).SetTitle("Настройки")
-
-	// Advanced
-	advanced := field.Object(
-		"scripts", field.Array(
-			field.Object(
-				"src", field.String().SetTitle("URL для загрузки скрипта"),
-				"type", field.String().SetTitle("Media Type скрипта"),
-				"content", field.String().SetTitle("Содержимое скрипта"),
-			),
-		).SetTitle("Дополнительные скрипты"),
-	).SetTitle("Расширенные настройки")
-
-	// Design
-	design := field.Object().WithIncludes("web_design").SetTitle("Дизайн")
-
-	//Variables
-	variables := field.Object(true, "variables", field.Array(getVarsField())).SetTitle("Переменные")
-
-	// Page
-	page := schema.New(
-		"content", content,
-		"seo", seo,
-		"settings", settings,
-		"advanced", advanced,
-		"design", design,
-		"variables", variables,
-	).WithMetadata(extension.MetadataKey, "perxisweb")
-
-	// Includes
-	page.SetIncludes(
-		field.Include{Ref: "hoop_item_options", Optional: true},
-		field.Include{Ref: "ext_web_pages_*", Optional: true},
-	)
-
-	//UI
-	page.Field.UI.ListView = &field.View{Options: map[string]interface{}{
-		"fields":    []string{"path", "name", "updated_at", "updated_by", "state"},
-		"sort":      []string{"path"},
-		"page_size": 50,
-	}}
-	page.Field.UI.Options["title"] = "name"
-	page.Field.UI.Options["key"] = "path"
-	page.Field.UI.Options["description"] = "path"
-	page.Field.UI.Widget = "Tabs"
-	page.Field.UI.Options["collection_icon"] = "ApartmentOutlined/FileTextOutlined"
-
-	_ = page.ConvertTypes()
-	page.ClearState()
-	return page
-}
-
-func getVarsSchema() (sch *schema.Schema) {
-	sch = schema.New(
-		"id", field.String(validate.Required()).SetTextSearch(true).SetTitle("Идентификатор переменной"),
-		"name", field.String().SetTextSearch(true).SetTitle("Название переменной"),
-		"value", field.String().SetTitle("Значение переменной"),
-	).WithMetadata(extension.MetadataKey, "perxisweb")
-	//UI
-	sch.Field.UI.ListView = &field.View{Options: map[string]interface{}{
-		"fields":    []string{"id", "name", "updated_at", "updated_by", "state"},
-		"page_size": 50,
-	}}
-
-	sch.Field.UI.Options["collection_icon"] = "SettingOutlined/FileExcelOutlined"
-	return sch
-}
-
-func getVarsField() *field.Field {
-	return &getVarsSchema().Field
-}
diff --git a/pkg/setup/config.go b/pkg/setup/config.go
index d7f68a90409ab338f8ff191e2f91bf80ddc0b130..48c763248b8c43afd05db3291ab4a1635890ba53 100644
--- a/pkg/setup/config.go
+++ b/pkg/setup/config.go
@@ -38,28 +38,20 @@ func (cfg *Config) Load(fsys fs.FS) (*Config, error) {
 		return nil, errors.Wrapf(err, "Can't load config. (fs=%v)", fsys)
 	}
 
-	if subFS, err := fs.Sub(fsys, "collections"); err == nil {
-		if err = cfg.Collections.Load(subFS); err != nil && !errors.Is(err, fs.ErrNotExist) {
-			return nil, err
-		}
+	if err := cfg.Collections.Load(fsys, "collections"); err != nil && !errors.Is(err, fs.ErrNotExist) {
+		return nil, err
 	}
 
-	if subFS, err := fs.Sub(fsys, "items"); err == nil {
-		if err = cfg.Items.Load(subFS, DecodeItem()); err != nil && !errors.Is(err, fs.ErrNotExist) {
-			return nil, err
-		}
+	if err := cfg.Items.Load(fsys, "items", DecodeItem()); err != nil && !errors.Is(err, fs.ErrNotExist) {
+		return nil, err
 	}
 
-	if subFS, err := fs.Sub(fsys, "roles"); err == nil {
-		if err = cfg.Roles.Load(subFS); err != nil && !errors.Is(err, fs.ErrNotExist) {
-			return nil, err
-		}
+	if err := cfg.Roles.Load(fsys, "roles"); err != nil && !errors.Is(err, fs.ErrNotExist) {
+		return nil, err
 	}
 
-	if subFS, err := fs.Sub(fsys, "clients"); err == nil {
-		if err = cfg.Clients.Load(subFS); err != nil && !errors.Is(err, fs.ErrNotExist) {
-			return nil, err
-		}
+	if err := cfg.Clients.Load(fsys, "clients"); err != nil && !errors.Is(err, fs.ErrNotExist) {
+		return nil, err
 	}
 
 	return cfg, nil
diff --git a/pkg/setup/entity.go b/pkg/setup/entity.go
index 69cd2c8d5ef4224bbc270c0c8cbb8df1fdfa1bf1..f9d52a409287a3b63a2e242b7216762707771fe6 100644
--- a/pkg/setup/entity.go
+++ b/pkg/setup/entity.go
@@ -120,9 +120,9 @@ func (l *EntityList[C, T]) GetIDs() []string {
 }
 
 // Load загружает сущности в список EntityList из указанной файловой системы
-func (l *EntityList[C, T]) Load(fsys fs.FS, opt ...EntityOption[C, T]) error {
-	assets := perxis.NewAssets[T]()
-	items, err := assets.FromFS(fsys)
+func (l *EntityList[C, T]) Load(fsys fs.FS, dir string, opt ...EntityOption[C, T]) error {
+	assets := perxis.NewAssets[T](fsys)
+	items, err := assets.FromDir(dir)
 	if err != nil {
 		return err
 	}
@@ -133,8 +133,8 @@ func (l *EntityList[C, T]) Load(fsys fs.FS, opt ...EntityOption[C, T]) error {
 }
 
 // MustLoad загружает сущности в список EntityList из указанной файловой системы
-func (l *EntityList[C, T]) MustLoad(fsys fs.FS, opt ...EntityOption[C, T]) {
-	if err := l.Load(fsys, opt...); err != nil {
+func (l *EntityList[C, T]) MustLoad(fsys fs.FS, dir string, opt ...EntityOption[C, T]) {
+	if err := l.Load(fsys, dir, opt...); err != nil {
 		panic(err)
 	}
 }