diff --git a/data/external.yaml b/data/external.yaml
new file mode 100644
index 0000000..2721e76
--- /dev/null
+++ b/data/external.yaml
@@ -0,0 +1,38 @@
+Vibrant:
+ - src: https://cdn.jsdelivr.net/npm/node-vibrant@3.1.5/dist/vibrant.min.js
+ integrity: sha256-5NovOZc4iwiAWTYIFiIM7DxKUXKWvpVEuMEPLzcm5/g=
+ type: script
+
+PhotoSwipe:
+ - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js
+ integrity: sha256-ePwmChbbvXbsO02lbM3HoHbSHTHFAeChekF1xKJdleo=
+ type: script
+ defer: true
+
+ - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js
+ integrity: sha256-UKkzOn/w1mBxRmLLGrSeyB4e1xbrp4xylgAWb3M42pU=
+ type: script
+ defer: true
+
+ - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.css
+ integrity: sha256-c0uckgykQ9v5k+IqViZOZKc47Jn7KQil4/MP3ySA3F8=
+ type: style
+
+ - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.css
+ integrity: sha256-SBLU4vv6CA6lHsZ1XyTdhyjJxCjPif/TRkjnsyGAGnE=
+ type: style
+
+KaTeX:
+ - src: https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css
+ integrity: sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X
+ type: style
+
+ - src: https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js
+ integrity: sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4
+ type: script
+ defer: true
+
+ - src: https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js
+ integrity: sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa
+ type: script
+ defer: true
diff --git a/layouts/partials/article/components/math.html b/layouts/partials/article/components/math.html
index 0f85127..d05861c 100644
--- a/layouts/partials/article/components/math.html
+++ b/layouts/partials/article/components/math.html
@@ -1,14 +1,6 @@
-
-
-
-
+{{- partial "helper/external" (dict "Context" . "Namespace" "KaTeX") -}}
\ No newline at end of file
diff --git a/layouts/partials/article/components/photoswipe.html b/layouts/partials/article/components/photoswipe.html
index ed1c677..c33ff49 100644
--- a/layouts/partials/article/components/photoswipe.html
+++ b/layouts/partials/article/components/photoswipe.html
@@ -65,8 +65,4 @@
-
-
-
-
-
\ No newline at end of file
+{{- partial "helper/external" (dict "Context" . "Namespace" "PhotoSwipe") -}}
\ No newline at end of file
diff --git a/layouts/partials/footer/components/script.html b/layouts/partials/footer/components/script.html
index 08e357b..83522ff 100644
--- a/layouts/partials/footer/components/script.html
+++ b/layouts/partials/footer/components/script.html
@@ -1,5 +1,4 @@
-
+{{- partial "helper/external" (dict "Context" . "Namespace" "Vibrant") -}}
{{- $opts := dict "minify" hugo.IsProduction -}}
{{- $script := resources.Get "ts/main.ts" | js.Build $opts -}}
diff --git a/layouts/partials/helper/external.html b/layouts/partials/helper/external.html
new file mode 100644
index 0000000..e1505d4
--- /dev/null
+++ b/layouts/partials/helper/external.html
@@ -0,0 +1,29 @@
+{{- $List := index .Context.Site.Data.external .Namespace -}}
+{{- with $List -}}
+ {{- range . -}}
+ {{- if eq .type "script" -}}
+
+ {{- else if eq .type "style" -}}
+
+ {{- else -}}
+ {{- errorf "Error: unknown external resource type: %s" .type -}}
+ {{- end -}}
+ {{- end -}}
+{{- else -}}
+ {{- errorf "Error: external resource '%s' is not found" .Namespace -}}
+{{- end -}}
\ No newline at end of file