diff --git a/.github/workflows/release-beta.yml b/.github/workflows/release-beta.yml
index 1daf9235..08afa9ae 100644
--- a/.github/workflows/release-beta.yml
+++ b/.github/workflows/release-beta.yml
@@ -20,11 +20,18 @@ jobs:
           registry-url: https://registry.npmjs.org/
 
       - name: Install the dependencies
-        run: npm i
+        run: npm ci
 
       - name: Prepare BETA
         run: node scripts/beta-release.js $GITHUB_RUN_ID
 
+      - name: Run localization sync
+        run: npm run localization:sync
+        env:
+          TRANSLATION_API_KEY: ${{ secrets.TRANSLATION_API_KEY }}
+          TRANSLATION_API_LOCATION: ${{ secrets.TRANSLATION_API_LOCATION }}
+          TRANSLATION_API_URL: ${{ secrets.TRANSLATION_API_URL }}
+
       - name: Publish
         run: npx @vscode/vsce publish -p ${{ secrets.VSCE_PAT }} --baseImagesUrl https://raw.githubusercontent.com/estruyf/vscode-front-matter/dev
 
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 29c2beef..27861b5f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -20,11 +20,18 @@ jobs:
           registry-url: https://registry.npmjs.org/
 
       - name: Install the dependencies
-        run: npm i
+        run: npm ci
 
       - name: Prepare MAIN release
         run: node scripts/main-release.js
 
+      - name: Run localization sync
+        run: npm run localization:sync
+        env:
+          TRANSLATION_API_KEY: ${{ secrets.TRANSLATION_API_KEY }}
+          TRANSLATION_API_LOCATION: ${{ secrets.TRANSLATION_API_LOCATION }}
+          TRANSLATION_API_URL: ${{ secrets.TRANSLATION_API_URL }}
+
       - name: Publish
         run: npx @vscode/vsce publish -p ${{ secrets.VSCE_PAT }}
 
diff --git a/.gitignore b/.gitignore
index f850006d..94035d25 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,4 +11,5 @@ e2e/extensions
 e2e/sample
 
 localization.log
-localization.md
\ No newline at end of file
+localization.md
+.env
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d5e1447f..9b4da5b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,40 @@
 # Change Log
 
+## [9.3.0] - 2023-10-06 - [Release notes](https://beta.frontmatter.codes/updates/v9.3.0)
+
+### ✨ New features
+
+- [#80](https://github.com/estruyf/vscode-front-matter/issues/80): Minimal settings view for the Front Matter CMS
+- [#553](https://github.com/estruyf/vscode-front-matter/issues/553): New `frontMatter.config.dynamicFilePath` setting which allows you to dynamically update the settings from a custom JS file
+- [#563](https://github.com/estruyf/vscode-front-matter/issues/563): New `fieldCollection` to inherit/reuse fields in multiple content-types
+- [#653](https://github.com/estruyf/vscode-front-matter/issues/653): Retrieve the Astro Content Collections to allow content type generation
+- [#675](https://github.com/estruyf/vscode-front-matter/issues/675): Pinning content to the top of the content dashboard
+
+### 🎨 Enhancements
+
+- [#517](https://github.com/estruyf/vscode-front-matter/issues/517): Add `contentTypes` property to custom scripts to show/hide custom actions
+- [#517](https://github.com/estruyf/vscode-front-matter/issues/517): Added `frontMatter.panel.actions.disabled` setting to define which actions should be hidden
+- [#638](https://github.com/estruyf/vscode-front-matter/issues/638): Add Hexo support for the `_drafts` folder
+- [#659](https://github.com/estruyf/vscode-front-matter/issues/659): Implement a filter for the taxonomy dashboard
+- [#662](https://github.com/estruyf/vscode-front-matter/issues/662): Always show the `all articles` tab with the page counter
+- [#663](https://github.com/estruyf/vscode-front-matter/issues/663): Make card tags clickable to filter the view
+- [#669](https://github.com/estruyf/vscode-front-matter/issues/669): Add the video preview to the details panel + caption field
+- [#674](https://github.com/estruyf/vscode-front-matter/issues/674): Specify to disable content creation for a specific page folder
+- [#676](https://github.com/estruyf/vscode-front-matter/issues/676): Allow the `frontmatter.json` file to be placed in a sub-directory
+- [#677](https://github.com/estruyf/vscode-front-matter/issues/677): Added support for [Browse Lite](https://marketplace.visualstudio.com/items?itemName=antfu.browse-lite) extension to open preview when installed
+
+### 🐞 Fixes
+
+- [#623](https://github.com/estruyf/vscode-front-matter/issues/623): Fix issue where metadata is not maintained on file move
+- [#629](https://github.com/estruyf/vscode-front-matter/issues/629): Fix array indent to the new property
+- [#660](https://github.com/estruyf/vscode-front-matter/issues/660): Allow only to select unique content relationship values
+- [#661](https://github.com/estruyf/vscode-front-matter/issues/661): Fixing the dropdowns when used at the bottom of a collapsible group
+- [#664](https://github.com/estruyf/vscode-front-matter/issues/664): Fix for parsing draft status in Hexo and Jekyll
+- [#665](https://github.com/estruyf/vscode-front-matter/issues/665): Added `dev` parameter to Nuxt script
+- [#668](https://github.com/estruyf/vscode-front-matter/issues/668): Reset pagination on media search
+- [#678](https://github.com/estruyf/vscode-front-matter/issues/678): Check field type of `tags` fields for tags rendering on item cards
+- [#681](https://github.com/estruyf/vscode-front-matter/issues/681): Fix SVG icons which are used in the VSCode UI
+
 ## [9.2.0] - 2023-09-11
 
 ### ✨ New features
@@ -16,6 +51,7 @@
 - [#645](https://github.com/estruyf/vscode-front-matter/issues/645): French localization added (thanks to [Clément Barbaza](https://github.com/cba85))
 - [#649](https://github.com/estruyf/vscode-front-matter/issues/649): Parse optional variables from snippets
 - [#652](https://github.com/estruyf/vscode-front-matter/issues/652): Show the start/stop server buttons depending on the local terminal session
+- [#654](https://github.com/estruyf/vscode-front-matter/issues/654): Added a new action to open the content in the browser
 
 ### 🐞 Fixes
 
diff --git a/assets/icons/blockquote-dark.svg b/assets/icons/blockquote-dark.svg
index a9cebe94..a3149b7b 100644
--- a/assets/icons/blockquote-dark.svg
+++ b/assets/icons/blockquote-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M6 15h15" />
   <path d="M21 19h-15" />
diff --git a/assets/icons/blockquote-light.svg b/assets/icons/blockquote-light.svg
index eb10a05b..a23c1d57 100644
--- a/assets/icons/blockquote-light.svg
+++ b/assets/icons/blockquote-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M6 15h15" />
   <path d="M21 19h-15" />
diff --git a/assets/icons/bold-dark.svg b/assets/icons/bold-dark.svg
index 6ba1d39f..ed8bee37 100644
--- a/assets/icons/bold-dark.svg
+++ b/assets/icons/bold-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M7 5h6a3.5 3.5 0 0 1 0 7h-6z" />
   <path d="M13 12h1a3.5 3.5 0 0 1 0 7h-7v-7" />
diff --git a/assets/icons/bold-light.svg b/assets/icons/bold-light.svg
index 9c887220..dbf3bb3a 100644
--- a/assets/icons/bold-light.svg
+++ b/assets/icons/bold-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M7 5h6a3.5 3.5 0 0 1 0 7h-6z" />
   <path d="M13 12h1a3.5 3.5 0 0 1 0 7h-7v-7" />
diff --git a/assets/icons/chatbot-dark.svg b/assets/icons/chatbot-dark.svg
index 718e178a..e2c46f5c 100644
--- a/assets/icons/chatbot-dark.svg
+++ b/assets/icons/chatbot-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 32 32">
   <path fill="#C5C5C5" d="M16 19a6.99 6.99 0 0 1-5.833-3.129l1.666-1.107a5 5 0 0 0 8.334 0l1.666 1.107A6.99 6.99 0 0 1 16 19zm4-11a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2zm-8 0a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2z"/>
   <path fill="#C5C5C5" d="M17.736 30L16 29l4-7h6a1.997 1.997 0 0 0 2-2V6a1.997 1.997 0 0 0-2-2H6a1.997 1.997 0 0 0-2 2v14a1.997 1.997 0 0 0 2 2h9v2H6a4 4 0 0 1-4-4V6a3.999 3.999 0 0 1 4-4h20a3.999 3.999 0 0 1 4 4v14a4 4 0 0 1-4 4h-4.835Z"/>
 </svg>
\ No newline at end of file
diff --git a/assets/icons/chatbot-light.svg b/assets/icons/chatbot-light.svg
index 5489e3e7..3f7ee554 100644
--- a/assets/icons/chatbot-light.svg
+++ b/assets/icons/chatbot-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 32 32">
   <path fill="#424242" d="M16 19a6.99 6.99 0 0 1-5.833-3.129l1.666-1.107a5 5 0 0 0 8.334 0l1.666 1.107A6.99 6.99 0 0 1 16 19zm4-11a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2zm-8 0a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2z"/>
   <path fill="#424242" d="M17.736 30L16 29l4-7h6a1.997 1.997 0 0 0 2-2V6a1.997 1.997 0 0 0-2-2H6a1.997 1.997 0 0 0-2 2v14a1.997 1.997 0 0 0 2 2h9v2H6a4 4 0 0 1-4-4V6a3.999 3.999 0 0 1 4-4h20a3.999 3.999 0 0 1 4 4v14a4 4 0 0 1-4 4h-4.835Z"/>
 </svg>
\ No newline at end of file
diff --git a/assets/icons/close-dark.svg b/assets/icons/close-dark.svg
index 257a84b0..3443b4df 100644
--- a/assets/icons/close-dark.svg
+++ b/assets/icons/close-dark.svg
@@ -1,4 +1,4 @@
-<svg width="32px" height="32px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#C5C5C5">
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#C5C5C5">
   <path d="M9 9H4v1h5V9z" />
   <path fill-rule="evenodd" clip-rule="evenodd" d="M5 3l1-1h7l1 1v7l-1 1h-2v2l-1 1H3l-1-1V6l1-1h2V3zm1 2h4l1 1v4h2V3H6v2zm4 1H3v7h7V6z" />
 </svg>
\ No newline at end of file
diff --git a/assets/icons/close-light.svg b/assets/icons/close-light.svg
index b9270b95..382ccd13 100644
--- a/assets/icons/close-light.svg
+++ b/assets/icons/close-light.svg
@@ -1,4 +1,4 @@
-<svg width="32px" height="32px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#424242">
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#424242">
   <path d="M9 9H4v1h5V9z" />
   <path fill-rule="evenodd" clip-rule="evenodd" d="M5 3l1-1h7l1 1v7l-1 1h-2v2l-1 1H3l-1-1V6l1-1h2V3zm1 2h4l1 1v4h2V3H6v2zm4 1H3v7h7V6z" />
 </svg>
\ No newline at end of file
diff --git a/assets/icons/code-dark.svg b/assets/icons/code-dark.svg
index a99e9aeb..ec2cc1dc 100644
--- a/assets/icons/code-dark.svg
+++ b/assets/icons/code-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <polyline points="7 8 3 12 7 16" />
   <polyline points="17 8 21 12 17 16" />
diff --git a/assets/icons/code-light.svg b/assets/icons/code-light.svg
index 1c0e436e..ff03e62b 100644
--- a/assets/icons/code-light.svg
+++ b/assets/icons/code-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <polyline points="7 8 3 12 7 16" />
   <polyline points="17 8 21 12 17 16" />
diff --git a/assets/icons/codeblock-dark.svg b/assets/icons/codeblock-dark.svg
index 8145c45f..36ff9942 100644
--- a/assets/icons/codeblock-dark.svg
+++ b/assets/icons/codeblock-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M9 12h6" />
   <path d="M12 9v6" />
diff --git a/assets/icons/codeblock-light.svg b/assets/icons/codeblock-light.svg
index 29714eb5..9266aeba 100644
--- a/assets/icons/codeblock-light.svg
+++ b/assets/icons/codeblock-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M9 12h6" />
   <path d="M12 9v6" />
diff --git a/assets/icons/heading-dark.svg b/assets/icons/heading-dark.svg
index 12e37896..394f9d96 100644
--- a/assets/icons/heading-dark.svg
+++ b/assets/icons/heading-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M7 12h10" />
   <path d="M7 4v16" />
diff --git a/assets/icons/heading-light.svg b/assets/icons/heading-light.svg
index 39010990..ef9a244d 100644
--- a/assets/icons/heading-light.svg
+++ b/assets/icons/heading-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M7 12h10" />
   <path d="M7 4v16" />
diff --git a/assets/icons/italic-dark.svg b/assets/icons/italic-dark.svg
index ac651c36..54d5c6db 100644
--- a/assets/icons/italic-dark.svg
+++ b/assets/icons/italic-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <line x1="11" y1="5" x2="17" y2="5" />
   <line x1="7" y1="19" x2="13" y2="19" />
diff --git a/assets/icons/italic-light.svg b/assets/icons/italic-light.svg
index 427ab51d..e045ebcc 100644
--- a/assets/icons/italic-light.svg
+++ b/assets/icons/italic-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <line x1="11" y1="5" x2="17" y2="5" />
   <line x1="7" y1="19" x2="13" y2="19" />
diff --git a/assets/icons/media-dark.svg b/assets/icons/media-dark.svg
index 65377af6..a8ba726b 100644
--- a/assets/icons/media-dark.svg
+++ b/assets/icons/media-dark.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="#C5C5C5" width="24" height="24">
+<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="#C5C5C5" width="16" height="16">
   <path fillRule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clipRule="evenodd" />
 </svg>
\ No newline at end of file
diff --git a/assets/icons/media-light.svg b/assets/icons/media-light.svg
index a382f5cc..cc126944 100644
--- a/assets/icons/media-light.svg
+++ b/assets/icons/media-light.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="#424242" width="24" height="24">
+<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="#424242" width="16" height="16">
   <path fillRule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clipRule="evenodd" />
 </svg>
\ No newline at end of file
diff --git a/assets/icons/options-dark.svg b/assets/icons/options-dark.svg
index 0c0f9b9b..034aafe1 100644
--- a/assets/icons/options-dark.svg
+++ b/assets/icons/options-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <circle cx="12" cy="12" r="9" />
   <line x1="8" y1="12" x2="8" y2="12.01" />
diff --git a/assets/icons/options-light.svg b/assets/icons/options-light.svg
index b5c10374..dd180058 100644
--- a/assets/icons/options-light.svg
+++ b/assets/icons/options-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <circle cx="12" cy="12" r="9" />
   <line x1="8" y1="12" x2="8" y2="12.01" />
diff --git a/assets/icons/ordered-list-dark.svg b/assets/icons/ordered-list-dark.svg
index 1d351b8e..99a330b9 100644
--- a/assets/icons/ordered-list-dark.svg
+++ b/assets/icons/ordered-list-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list-numbers" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list-numbers" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M11 6h9" />
   <path d="M11 12h9" />
diff --git a/assets/icons/ordered-list-light.svg b/assets/icons/ordered-list-light.svg
index b238e15b..aa3f155e 100644
--- a/assets/icons/ordered-list-light.svg
+++ b/assets/icons/ordered-list-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list-numbers" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list-numbers" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M11 6h9" />
   <path d="M11 12h9" />
diff --git a/assets/icons/scissors-dark.svg b/assets/icons/scissors-dark.svg
index 514110d3..2e81042b 100644
--- a/assets/icons/scissors-dark.svg
+++ b/assets/icons/scissors-dark.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#C5C5C5" stroke-width="2">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#C5C5C5" stroke-width="2">
   <path stroke-linecap="round" stroke-linejoin="round" d="M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z" />
 </svg>
\ No newline at end of file
diff --git a/assets/icons/scissors-light.svg b/assets/icons/scissors-light.svg
index 780b674e..a2e41ffb 100644
--- a/assets/icons/scissors-light.svg
+++ b/assets/icons/scissors-light.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#424242" stroke-width="2">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#424242" stroke-width="2">
   <path stroke-linecap="round" stroke-linejoin="round" d="M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z" />
 </svg>
\ No newline at end of file
diff --git a/assets/icons/strikethrough-dark.svg b/assets/icons/strikethrough-dark.svg
index a8a8a038..f2fd6bd9 100644
--- a/assets/icons/strikethrough-dark.svg
+++ b/assets/icons/strikethrough-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M7 5v9a5 5 0 0 0 10 0v-9" />
   <path d="M4 12h16" />
diff --git a/assets/icons/strikethrough-light.svg b/assets/icons/strikethrough-light.svg
index bd67607c..b91b9af1 100644
--- a/assets/icons/strikethrough-light.svg
+++ b/assets/icons/strikethrough-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <path d="M7 5v9a5 5 0 0 0 10 0v-9" />
   <path d="M4 12h16" />
diff --git a/assets/icons/unordered-list-dark.svg b/assets/icons/unordered-list-dark.svg
index 9a66e6c9..2b37cc79 100644
--- a/assets/icons/unordered-list-dark.svg
+++ b/assets/icons/unordered-list-dark.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#C5C5C5" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <line x1="9" y1="6" x2="20" y2="6" />
   <line x1="9" y1="12" x2="20" y2="12" />
diff --git a/assets/icons/unordered-list-light.svg b/assets/icons/unordered-list-light.svg
index 29de1d80..467916ee 100644
--- a/assets/icons/unordered-list-light.svg
+++ b/assets/icons/unordered-list-light.svg
@@ -1,4 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-list" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="#424242" fill="none" stroke-linecap="round" stroke-linejoin="round">
   <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
   <line x1="9" y1="6" x2="20" y2="6" />
   <line x1="9" y1="12" x2="20" y2="12" />
diff --git a/assets/media/styles.css b/assets/media/styles.css
index d8e8f4a1..fd384c80 100644
--- a/assets/media/styles.css
+++ b/assets/media/styles.css
@@ -66,43 +66,6 @@
   padding: 1rem 1.25rem;
 }
 
-.spinner,
-.spinner:before,
-.spinner:after {
-  border-radius: 50%;
-  width: 2em;
-  height: 2em;
-  animation-fill-mode: both;
-  animation: load7 1.8s infinite ease-in-out;
-}
-
-.spinner {
-  color: var(--vscode-panelSectionHeader-foreground);
-  font-size: 10px;
-  margin: 80px auto;
-  position: relative;
-  text-indent: -9999em;
-  transform: translateZ(0);
-  animation-delay: -0.16s;
-}
-
-.spinner:before,
-.spinner:after {
-  content: '';
-  position: absolute;
-  top: 0;
-}
-
-.spinner:before {
-  left: -3.5em;
-  -webkit-animation-delay: -0.32s;
-  animation-delay: -0.32s;
-}
-
-.spinner:after {
-  left: 3.5em;
-}
-
 .frontmatter {
   padding-top: 0;
   padding-bottom: var(--input-margin-vertical);
diff --git a/l10n/bundle.l10n.de.json b/l10n/bundle.l10n.de.json
index 926f68bd..cc624e59 100644
--- a/l10n/bundle.l10n.de.json
+++ b/l10n/bundle.l10n.de.json
@@ -336,5 +336,29 @@
   "dashboard.steps.stepsToGetStarted.template.name": "Verwende eine Konfigurationsvorlage",
   "dashboard.steps.stepsToGetStarted.template.description": "Wählen Sie eine Vorlage aus, um die Datei frontmatter.json mit den empfohlenen Einstellungen vorzufüllen.",
   "listeners.dashboard.settingsListener.triggerTemplate.notification": "Vorlagendateien kopiert.",
-  "common.openOnWebsite": "Auf der Website öffnen"
+  "common.openOnWebsite": "Auf der Website öffnen",
+  "common.filter.value": "Filtern nach {0}",
+  "dashboard.media.detailsSlideOver.unmapped.description": "Möchten Sie die Metadaten von nicht zugeordneten Dateien neu zuordnen?",
+  "common.settings": "Einstellungen",
+  "common.refreshSettings": "Einstellungen aktualisieren",
+  "common.pin": "Stecknadel",
+  "common.unpin": "Losheften",
+  "settings.view.common": "Gemeinsam",
+  "settings.view.contentFolders": "Inhaltsordner",
+  "settings.view.astro": "Astro",
+  "settings.openOnStartup": "Öffnen Sie das Dashboard beim Start",
+  "settings.contentTypes": "Inhaltstypen",
+  "settings.contentFolders": "Inhaltsordner",
+  "settings.diagnostic": "Diagnostisch",
+  "settings.diagnostic.description": "Sie können die Diagnose ausführen, um die gesamte Front Matter CMS-Konfiguration zu überprüfen.",
+  "settings.diagnostic.link": "Führen Sie eine vollständige Diagnose durch",
+  "settings.commonSettings.website.title": "Website- und SSG-Einstellungen",
+  "settings.commonSettings.previewUrl": "Vorschau-URL",
+  "settings.commonSettings.websiteUrl": "Website-URL",
+  "settings.commonSettings.startCommand": "SSG/Framework-Startbefehl",
+  "dashboard.contents.overview.pinned": "Angeheftet",
+  "dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Erstellen Sie Content-Typen für Ihre Astro Content Collections",
+  "dashboard.welcomeScreen.link.documentation.label": "Dokumentation",
+  "dashboard.configuration.astro.astroContentTypes.empty": "Es wurden keine Astro Content Collections gefunden.",
+  "dashboard.configuration.astro.astroContentTypes.description": "Die folgenden Astro Content Collections und können verwendet werden, um einen Inhaltstyp zu generieren."
 }
\ No newline at end of file
diff --git a/l10n/bundle.l10n.fr.json b/l10n/bundle.l10n.fr.json
index bbb1e570..68d68d09 100644
--- a/l10n/bundle.l10n.fr.json
+++ b/l10n/bundle.l10n.fr.json
@@ -336,5 +336,29 @@
   "dashboard.steps.stepsToGetStarted.template.name": "Utiliser un modèle de configuration",
   "dashboard.steps.stepsToGetStarted.template.description": "Sélectionnez un modèle pour préremplir le fichier frontmatter.json avec les paramètres recommandés.",
   "listeners.dashboard.settingsListener.triggerTemplate.notification": "Fichiers de modèle copiés.",
-  "common.openOnWebsite": "Ouvrir sur le site web"
+  "common.openOnWebsite": "Ouvrir sur le site web",
+  "common.filter.value": "Filtrer par {0}",
+  "dashboard.media.detailsSlideOver.unmapped.description": "Voulez-vous remapper les métadonnées des fichiers non mappés?",
+  "common.settings": "Paramètres",
+  "common.refreshSettings": "Actualiser les paramètres",
+  "common.pin": "Épingler",
+  "common.unpin": "Détacher",
+  "settings.view.common": "Commun",
+  "settings.view.contentFolders": "Dossiers de contenu",
+  "settings.view.astro": "Astro",
+  "settings.openOnStartup": "Ouvrir le tableau de bord au démarrage",
+  "settings.contentTypes": "Types de contenu",
+  "settings.contentFolders": "Dossiers de contenu",
+  "settings.diagnostic": "Diagnostique",
+  "settings.diagnostic.description": "Vous pouvez exécuter les diagnostics pour vérifier l’ensemble de la configuration de Front Matter CMS.",
+  "settings.diagnostic.link": "Exécuter des diagnostics complets",
+  "settings.commonSettings.website.title": "Paramètres du site Web et SSG",
+  "settings.commonSettings.previewUrl": "URL d’aperçu",
+  "settings.commonSettings.websiteUrl": "URL du site Web",
+  "settings.commonSettings.startCommand": "Commande de démarrage SSG/Framework",
+  "dashboard.contents.overview.pinned": "Épinglé",
+  "dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Créer des types de contenu pour vos collections de contenu Astro",
+  "dashboard.welcomeScreen.link.documentation.label": "Documentation",
+  "dashboard.configuration.astro.astroContentTypes.empty": "Aucune collection de contenu Astro trouvée.",
+  "dashboard.configuration.astro.astroContentTypes.description": "Les collections de contenu Astro suivantes peuvent être utilisées pour générer un type de contenu."
 }
\ No newline at end of file
diff --git a/l10n/bundle.l10n.it.json b/l10n/bundle.l10n.it.json
index b35eba59..aa38a8b4 100644
--- a/l10n/bundle.l10n.it.json
+++ b/l10n/bundle.l10n.it.json
@@ -336,5 +336,29 @@
   "dashboard.steps.stepsToGetStarted.template.name": "Usa un modello di configurazione",
   "dashboard.steps.stepsToGetStarted.template.description": "Seleziona un modello per riempire in anticipo il file frontmatter.json con le impostazioni consigliate.",
   "listeners.dashboard.settingsListener.triggerTemplate.notification": "File del modello copiati.",
-  "common.openOnWebsite": "Apri sul sito web"
+  "common.openOnWebsite": "Apri sul sito web",
+  "common.filter.value": "Filtra per {0}",
+  "dashboard.media.detailsSlideOver.unmapped.description": "Vuoi riassegnare i metadati dei file non mappati?",
+  "common.settings": "Impostazioni",
+  "common.refreshSettings": "Aggiorna impostazioni",
+  "common.pin": "Spilla",
+  "common.unpin": "Rimuovere",
+  "settings.view.common": "Comune",
+  "settings.view.contentFolders": "Cartelle di contenuto",
+  "settings.view.astro": "Astro",
+  "settings.openOnStartup": "Apri dashboard all'avvio",
+  "settings.contentTypes": "Tipi di contenuto",
+  "settings.contentFolders": "Cartelle di contenuto",
+  "settings.diagnostic": "Diagnostico",
+  "settings.diagnostic.description": "È possibile eseguire la diagnostica per verificare l'intera configurazione CMS di Front Matter.",
+  "settings.diagnostic.link": "Eseguire la diagnostica completa",
+  "settings.commonSettings.website.title": "Impostazioni del sito Web e del SSG",
+  "settings.commonSettings.previewUrl": "URL di anteprima",
+  "settings.commonSettings.websiteUrl": "URL del sito web",
+  "settings.commonSettings.startCommand": "Comando di avvio SSG/Framework",
+  "dashboard.contents.overview.pinned": "Appuntato",
+  "dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Crea tipi di contenuto per le tue raccolte di contenuti Astro",
+  "dashboard.welcomeScreen.link.documentation.label": "Documentazione",
+  "dashboard.configuration.astro.astroContentTypes.empty": "Nessuna raccolta di contenuti Astro trovata.",
+  "dashboard.configuration.astro.astroContentTypes.description": "Le seguenti raccolte di contenuti Astro e possono essere utilizzate per generare un tipo di contenuto."
 }
\ No newline at end of file
diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json
index d9d1fc21..2ae52994 100644
--- a/l10n/bundle.l10n.ja.json
+++ b/l10n/bundle.l10n.ja.json
@@ -298,7 +298,7 @@
   "panel.preview.title": "プレビューを表示",
   "panel.publishAction.publish": "公開",
   "panel.publishAction.unpublish": "下書きに戻す",
-  "panel.seoDetails.recommended": "🚧: Recommended",
+  "panel.seoDetails.recommended": "推奨",
   "panel.seoKeywordInfo.density": "キーワード出現率 {0} *",
   "panel.seoKeywordInfo.validInfo.label": "見出しへの利用",
   "panel.seoKeywordInfo.validInfo.content": "本文",
@@ -336,5 +336,29 @@
   "dashboard.steps.stepsToGetStarted.template.name": "設定テンプレートを使用する",
   "dashboard.steps.stepsToGetStarted.template.description": "おすすめの設定でfrontmatter.jsonファイルを事前に埋めるテンプレートを選択します。",
   "listeners.dashboard.settingsListener.triggerTemplate.notification": "テンプレートファイルがコピーされました。",
-  "common.openOnWebsite": "ウェブサイトで開く"
+  "common.openOnWebsite": "ウェブサイトで開く",
+  "common.filter.value": "{0} でフィルタリング",
+  "dashboard.media.detailsSlideOver.unmapped.description": "未割り当てのファイルのメタデータを再マップしますか",
+  "common.settings": "設定",
+  "common.refreshSettings": "設定の更新",
+  "common.pin": "ピン",
+  "common.unpin": "解除",
+  "settings.view.common": "コモン",
+  "settings.view.contentFolders": "コンテンツ フォルダー",
+  "settings.view.astro": "アストロ",
+  "settings.openOnStartup": "起動時にダッシュボードを開く",
+  "settings.contentTypes": "コンテンツ タイプ",
+  "settings.contentFolders": "コンテンツ フォルダー",
+  "settings.diagnostic": "診断",
+  "settings.diagnostic.description": "診断プログラムを実行して、フロントマター CMS 構成全体を確認できます。",
+  "settings.diagnostic.link": "完全診断を実行する",
+  "settings.commonSettings.website.title": "ウェブサイトとSSGの設定",
+  "settings.commonSettings.previewUrl": "URL のプレビュー",
+  "settings.commonSettings.websiteUrl": "ウェブサイトの URL",
+  "settings.commonSettings.startCommand": "SSG/フレームワーク起動コマンド",
+  "dashboard.contents.overview.pinned": "固定",
+  "dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Astroコンテンツコレクションのコンテンツタイプを作成する",
+  "dashboard.welcomeScreen.link.documentation.label": "ドキュメンテーション",
+  "dashboard.configuration.astro.astroContentTypes.empty": "Astroコンテンツコレクションが見つかりません。",
+  "dashboard.configuration.astro.astroContentTypes.description": "以下のAstroコンテンツコレクションは、コンテンツタイプを生成するために使用できます。"
 }
\ No newline at end of file
diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json
index e620f74b..2bcf9160 100644
--- a/l10n/bundle.l10n.json
+++ b/l10n/bundle.l10n.json
@@ -20,8 +20,28 @@
   "common.slug": "Slug",
   "common.support": "Support",
   "common.remove.value": "Remove {0}",
+  "common.filter.value": "Filter by {0}",
   "common.error.message": "Sorry, something went wrong.",
   "common.openOnWebsite": "Open on website",
+  "common.settings": "Settings",
+  "common.refreshSettings": "Refresh settings",
+  "common.pin": "Pin",
+  "common.unpin": "Unpin",
+
+  "settings.view.common": "Common",
+  "settings.view.contentFolders": "Content folders",
+  "settings.view.astro": "Astro",
+  "settings.openOnStartup": "Open dashboard on startup",
+  "settings.contentTypes": "Content types",
+  "settings.contentFolders": "Content folders",
+  "settings.diagnostic": "Diagnostic",
+  "settings.diagnostic.description": "You can run the diagnostics to check the whole Front Matter CMS configuration.",
+  "settings.diagnostic.link": "Run full diagnostics",
+
+  "settings.commonSettings.website.title": "Website and SSG settings",
+  "settings.commonSettings.previewUrl": "Preview URL",
+  "settings.commonSettings.websiteUrl": "Website URL",
+  "settings.commonSettings.startCommand": "SSG/Framework start command",
 
   "developer.title": "Developer mode",
   "developer.reload.title": "Reload the dashboard",
@@ -60,6 +80,7 @@
 
   "dashboard.contents.overview.noMarkdown": "No Markdown to show",
   "dashboard.contents.overview.noFolders": "Make sure you registered a content folder in your project to let Front Matter find the contents.",
+  "dashboard.contents.overview.pinned": "Pinned",
 
   "dashboard.contents.status.draft": "Draft",
   "dashboard.contents.status.published": "Published",
@@ -245,6 +266,7 @@
   "dashboard.steps.stepsToGetStarted.showDashboard.description": "Once all actions are completed, the dashboard can be loaded.",
   "dashboard.steps.stepsToGetStarted.template.name": "Use a configuration template",
   "dashboard.steps.stepsToGetStarted.template.description": "Select a template to prefill the frontmatter.json file with the recommended settings.",
+  "dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Create Content-Types for your Astro Content Collections",
 
   "dashboard.taxonomyView.button.add.title": "Add {0} to taxonomy settings",
   "dashboard.taxonomyView.button.edit.title": "Edit {0}",
@@ -274,7 +296,8 @@
   "dashboard.welcomeScreen.thanks": "Thank you for using Front Matter!",
   "dashboard.welcomeScreen.description": "We try to aim to make Front Matter as easy to use as possible, but if you have any questions or suggestions. Please don't hesitate to reach out to us on GitHub.",
   "dashboard.welcomeScreen.link.github.title": "GitHub",
-  "dashboard.welcomeScreen.link.github.label": "GitHub / Documentation",
+  "dashboard.welcomeScreen.link.github.label": "GitHub",
+  "dashboard.welcomeScreen.link.documentation.label": "Documentation",
   "dashboard.welcomeScreen.link.sponsor.title": "Become a sponsor",
   "dashboard.welcomeScreen.link.sponsor.label": "Sponsor",
   "dashboard.welcomeScreen.link.review.title": "Write a review",
@@ -283,6 +306,11 @@
   "dashboard.welcomeScreen.actions.description": "You can also use the extension from the Front Matter side panel. There you will find the actions you can perform specifically for your pages.",
   "dashboard.welcomeScreen.actions.thanks": "We hope you enjoy Front Matter!",
 
+  "dashboard.media.detailsSlideOver.unmapped.description": "Do you want to remap the metadata of unmapped files?",
+
+  "dashboard.configuration.astro.astroContentTypes.empty": "No Astro Content Collections found.",
+  "dashboard.configuration.astro.astroContentTypes.description": "The following Astro Content Collections and can be used to generate a content-type.",
+
   "panel.contentType.contentTypeValidator.title": "Content-type",
   "panel.contentType.contentTypeValidator.hint": "We noticed field differences between the content-type and the front matter data. \n Would you like to create, update, or set the content-type for this content?",
   "panel.contentType.contentTypeValidator.button.create": "Create content-type",
@@ -349,7 +377,6 @@
   "panel.baseView.initialize": "Initialize project",
   "panel.baseView.actions.title": "Actions",
   "panel.baseView.action.openDashboard": "Open dashboard",
-  "panel.baseView.action.openPreview": "Open preview",
   "panel.baseView.action.createContent": "Create content",
   "panel.baseView.empty": "Open a file to see more actions",
 
diff --git a/package-lock.json b/package-lock.json
index 340b476c..b0f7cd22 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "vscode-front-matter-beta",
-  "version": "9.2.0",
+  "version": "9.3.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "vscode-front-matter-beta",
-      "version": "9.2.0",
+      "version": "9.3.0",
       "license": "MIT",
       "devDependencies": {
         "@actions/core": "^1.10.0",
@@ -41,7 +41,7 @@
         "@typescript-eslint/parser": "^5.50.0",
         "@vscode/codicons": "0.0.20",
         "@vscode/l10n": "^0.0.14",
-        "@vscode/webview-ui-toolkit": "^0.9.3",
+        "@vscode/webview-ui-toolkit": "^1.2.2",
         "@webpack-cli/serve": "^1.7.0",
         "ajv": "^8.12.0",
         "array-move": "^4.0.0",
@@ -51,6 +51,7 @@
         "cheerio": "1.0.0-rc.12",
         "css-loader": "5.2.7",
         "date-fns": "2.23.0",
+        "dotenv": "^16.3.1",
         "downshift": "6.0.6",
         "eslint": "^8.33.0",
         "fuse.js": "6.5.3",
@@ -110,6 +111,7 @@
         "webpack-bundle-analyzer": "^4.7.0",
         "webpack-cli": "^4.10.0",
         "webpack-dev-server": "^4.11.1",
+        "webpack-ignore-dynamic-require": "^1.0.0",
         "yaml": "^2.2.1",
         "yawn-yaml": "^1.5.0"
       },
@@ -1623,13 +1625,13 @@
       }
     },
     "node_modules/@vscode/webview-ui-toolkit": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-0.9.3.tgz",
-      "integrity": "sha512-uEEpTVA21zkHtWMR8TPT7vbIZ1+tvfhQPThEdmmDjh0PulKPvaAVNqnGbQitU3F9GVqpq2AdIKAq6N1jFeBoXg==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.2.2.tgz",
+      "integrity": "sha512-xIQoF4FC3Xh6d7KNKIoIezSiFWYFuf6gQMdDyKueKBFGeKwaHWEn+dY2g3makvvEsNMEDji/woEwvg9QSbuUsw==",
       "dev": true,
       "dependencies": {
         "@microsoft/fast-element": "^1.6.2",
-        "@microsoft/fast-foundation": "^2.34.0",
+        "@microsoft/fast-foundation": "^2.38.0",
         "@microsoft/fast-react-wrapper": "^0.1.18"
       },
       "peerDependencies": {
@@ -3816,6 +3818,18 @@
         "tslib": "^1.10.0"
       }
     },
+    "node_modules/dotenv": {
+      "version": "16.3.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+      "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/motdotla/dotenv?sponsor=1"
+      }
+    },
     "node_modules/downshift": {
       "version": "6.0.6",
       "dev": true,
@@ -12724,6 +12738,12 @@
         }
       }
     },
+    "node_modules/webpack-ignore-dynamic-require": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/webpack-ignore-dynamic-require/-/webpack-ignore-dynamic-require-1.0.0.tgz",
+      "integrity": "sha512-WeGFPgwDochKPwizAu5XsHcPq3aaQLl2E+n1piD/VPGNUo5HIwrtURWNMfrPDfkHVOx+flkAihXbUiILAv5x4Q==",
+      "dev": true
+    },
     "node_modules/webpack-merge": {
       "version": "5.8.0",
       "dev": true,
@@ -14293,13 +14313,13 @@
       }
     },
     "@vscode/webview-ui-toolkit": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-0.9.3.tgz",
-      "integrity": "sha512-uEEpTVA21zkHtWMR8TPT7vbIZ1+tvfhQPThEdmmDjh0PulKPvaAVNqnGbQitU3F9GVqpq2AdIKAq6N1jFeBoXg==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.2.2.tgz",
+      "integrity": "sha512-xIQoF4FC3Xh6d7KNKIoIezSiFWYFuf6gQMdDyKueKBFGeKwaHWEn+dY2g3makvvEsNMEDji/woEwvg9QSbuUsw==",
       "dev": true,
       "requires": {
         "@microsoft/fast-element": "^1.6.2",
-        "@microsoft/fast-foundation": "^2.34.0",
+        "@microsoft/fast-foundation": "^2.38.0",
         "@microsoft/fast-react-wrapper": "^0.1.18"
       }
     },
@@ -15848,6 +15868,12 @@
         "tslib": "^1.10.0"
       }
     },
+    "dotenv": {
+      "version": "16.3.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+      "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+      "dev": true
+    },
     "downshift": {
       "version": "6.0.6",
       "dev": true,
@@ -21882,6 +21908,12 @@
         }
       }
     },
+    "webpack-ignore-dynamic-require": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/webpack-ignore-dynamic-require/-/webpack-ignore-dynamic-require-1.0.0.tgz",
+      "integrity": "sha512-WeGFPgwDochKPwizAu5XsHcPq3aaQLl2E+n1piD/VPGNUo5HIwrtURWNMfrPDfkHVOx+flkAihXbUiILAv5x4Q==",
+      "dev": true
+    },
     "webpack-merge": {
       "version": "5.8.0",
       "dev": true,
diff --git a/package.json b/package.json
index b5e24b60..10f2929c 100644
--- a/package.json
+++ b/package.json
@@ -3,15 +3,14 @@
   "displayName": "Front Matter CMS",
   "description": "Front Matter is a CMS that runs within Visual Studio Code. It gives you the power and control of a full-blown CMS while also providing you the flexibility and speed of the static site generator of your choice like: Hugo, Jekyll, Docusaurus, NextJs, Gatsby, and many more...",
   "icon": "assets/frontmatter-teal-128x128.png",
-  "version": "9.2.0",
+  "version": "9.3.0",
   "preview": false,
   "publisher": "eliostruyf",
   "galleryBanner": {
     "color": "#0e131f",
     "theme": "dark"
   },
-  "badges": [
-    {
+  "badges": [{
       "description": "version",
       "url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
       "href": "https://github.com/estruyf/vscode-front-matter"
@@ -71,8 +70,7 @@
         "**/.frontmatter/config/*.json": "jsonc"
       }
     },
-    "keybindings": [
-      {
+    "keybindings": [{
         "command": "frontMatter.dashboard",
         "key": "alt+d"
       },
@@ -90,24 +88,19 @@
       }
     ],
     "viewsContainers": {
-      "activitybar": [
-        {
-          "id": "frontmatter-explorer",
-          "title": "Front Matter",
-          "icon": "assets/frontmatter-short-min.svg"
-        }
-      ]
+      "activitybar": [{
+        "id": "frontmatter-explorer",
+        "title": "FM",
+        "icon": "$(fm-logo)"
+      }]
     },
     "views": {
-      "frontmatter-explorer": [
-        {
-          "id": "frontMatter.explorer",
-          "name": "Front Matter",
-          "icon": "assets/frontmatter-short-min.svg",
-          "contextualTitle": "Front Matter",
-          "type": "webview"
-        }
-      ]
+      "frontmatter-explorer": [{
+        "id": "frontMatter.explorer",
+        "name": "Front Matter",
+        "icon": "$(fm-logo)",
+        "type": "webview"
+      }]
     },
     "configuration": {
       "title": "%settings.configuration.title%",
@@ -161,6 +154,11 @@
             "type": "string"
           }
         },
+        "frontMatter.config.dynamicFilePath": {
+          "type": "string",
+          "markdownDescription": "%setting.frontMatter.config.dynamicFilePath.markdownDescription%",
+          "default": ""
+        },
         "frontMatter.content.autoUpdateDate": {
           "type": "boolean",
           "default": false,
@@ -170,8 +168,7 @@
         "frontMatter.content.defaultFileType": {
           "type": "string",
           "default": "md",
-          "oneOf": [
-            {
+          "oneOf": [{
               "enum": [
                 "md",
                 "mdx"
@@ -187,8 +184,7 @@
         "frontMatter.content.defaultSorting": {
           "type": "string",
           "default": "",
-          "oneOf": [
-            {
+          "oneOf": [{
               "enum": [
                 "LastModifiedAsc",
                 "LastModifiedDesc",
@@ -302,6 +298,11 @@
                 "items": {
                   "type": "string"
                 }
+              },
+              "disableCreation": {
+                "type": "boolean",
+                "default": false,
+                "description": "%setting.frontMatter.content.pageFolders.items.properties.disableCreation.description%"
               }
             },
             "additionalProperties": false,
@@ -535,8 +536,7 @@
               "command": {
                 "$id": "#scriptCommand",
                 "type": "string",
-                "anyOf": [
-                  {
+                "anyOf": [{
                     "enum": [
                       "node",
                       "bash",
@@ -580,6 +580,13 @@
                     }
                   }
                 }
+              },
+              "contentTypes": {
+                "type": "array",
+                "description": "%setting.frontMatter.custom.scripts.items.properties.contentTypes.description%",
+                "items": {
+                  "type": "string"
+                }
               }
             },
             "additionalProperties": false,
@@ -736,8 +743,7 @@
               "title",
               "file"
             ],
-            "anyOf": [
-              {
+            "anyOf": [{
                 "required": [
                   "schema"
                 ]
@@ -791,8 +797,7 @@
               "id",
               "path"
             ],
-            "anyOf": [
-              {
+            "anyOf": [{
                 "required": [
                   "schema"
                 ]
@@ -985,6 +990,20 @@
           "markdownDescription": "%setting.frontMatter.panel.freeform.markdownDescription%",
           "scope": "Panel"
         },
+        "frontMatter.panel.actions.disabled": {
+          "type": "array",
+          "default": [],
+          "markdownDescription": "%setting.frontMatter.panel.actions.disabeld.markdownDescription%",
+          "enum": [
+            "openDashboard",
+            "createContent",
+            "optimizeSlug",
+            "preview",
+            "openOnWebsite",
+            "startStopServer",
+            "customActions"
+          ]
+        },
         "frontMatter.preview.host": {
           "type": "string",
           "default": "",
@@ -1049,6 +1068,11 @@
                 ],
                 "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fileType.description%"
               },
+              "clearEmpty": {
+                "type": "boolean",
+                "default": false,
+                "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description%"
+              },
               "fields": {
                 "$id": "#contenttypefield",
                 "type": "array",
@@ -1080,7 +1104,8 @@
                         "divider",
                         "heading",
                         "customField",
-                        "contentRelationship"
+                        "contentRelationship",
+                        "fieldCollection"
                       ],
                       "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.type.description%"
                     },
@@ -1160,8 +1185,7 @@
                       "default": "",
                       "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description%",
                       "not": {
-                        "anyOf": [
-                          {
+                        "anyOf": [{
                             "const": ""
                           },
                           {
@@ -1281,11 +1305,6 @@
                       "default": false,
                       "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.required.description%"
                     },
-                    "clearEmpty": {
-                      "type": "boolean",
-                      "default": false,
-                      "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description%"
-                    },
                     "customType": {
                       "type": "string",
                       "default": "",
@@ -1355,8 +1374,7 @@
                     "type",
                     "name"
                   ],
-                  "allOf": [
-                    {
+                  "allOf": [{
                       "if": {
                         "properties": {
                           "type": {
@@ -1483,6 +1501,20 @@
                         ]
                       }
                     },
+                    {
+                      "if": {
+                        "properties": {
+                          "type": {
+                            "const": "fieldCollection"
+                          }
+                        }
+                      },
+                      "then": {
+                        "required": [
+                          "fieldGroup"
+                        ]
+                      }
+                    },
                     {
                       "if": {
                         "properties": {
@@ -1542,51 +1574,48 @@
               "fields"
             ]
           },
-          "default": [
-            {
-              "name": "default",
-              "pageBundle": false,
-              "fields": [
-                {
-                  "title": "Title",
-                  "name": "title",
-                  "type": "string"
-                },
-                {
-                  "title": "Description",
-                  "name": "description",
-                  "type": "string"
-                },
-                {
-                  "title": "Publishing date",
-                  "name": "date",
-                  "type": "datetime",
-                  "default": "{{now}}",
-                  "isPublishDate": true
-                },
-                {
-                  "title": "Content preview",
-                  "name": "preview",
-                  "type": "image"
-                },
-                {
-                  "title": "Is in draft",
-                  "name": "draft",
-                  "type": "boolean"
-                },
-                {
-                  "title": "Tags",
-                  "name": "tags",
-                  "type": "tags"
-                },
-                {
-                  "title": "Categories",
-                  "name": "categories",
-                  "type": "categories"
-                }
-              ]
-            }
-          ],
+          "default": [{
+            "name": "default",
+            "pageBundle": false,
+            "fields": [{
+                "title": "Title",
+                "name": "title",
+                "type": "string"
+              },
+              {
+                "title": "Description",
+                "name": "description",
+                "type": "string"
+              },
+              {
+                "title": "Publishing date",
+                "name": "date",
+                "type": "datetime",
+                "default": "{{now}}",
+                "isPublishDate": true
+              },
+              {
+                "title": "Content preview",
+                "name": "preview",
+                "type": "image"
+              },
+              {
+                "title": "Is in draft",
+                "name": "draft",
+                "type": "boolean"
+              },
+              {
+                "title": "Tags",
+                "name": "tags",
+                "type": "tags"
+              },
+              {
+                "title": "Categories",
+                "name": "categories",
+                "type": "categories"
+              }
+            ]
+          }],
           "scope": "Taxonomy"
         },
         "frontMatter.taxonomy.customTaxonomy": {
@@ -1599,8 +1628,7 @@
                 "type": "string",
                 "description": "%setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description%",
                 "not": {
-                  "anyOf": [
-                    {
+                  "anyOf": [{
                       "const": ""
                     },
                     {
@@ -1786,8 +1814,7 @@
         }
       }
     },
-    "commands": [
-      {
+    "commands": [{
         "command": "frontMatter.project.switch",
         "title": "%command.frontMatter.project.switch%",
         "category": "Front Matter",
@@ -1846,10 +1873,7 @@
         "command": "frontMatter.dashboard.close",
         "title": "%command.frontMatter.dashboard.close%",
         "category": "Front Matter",
-        "icon": {
-          "dark": "/assets/icons/frontmatter-small-teal.svg",
-          "light": "/assets/icons/frontmatter-small-teal.svg"
-        }
+        "icon": "$(fm-logo)"
       },
       {
         "command": "frontMatter.markup.code",
@@ -1994,46 +2018,31 @@
         "command": "frontMatter.dashboard",
         "title": "%command.frontMatter.dashboard%",
         "category": "Front Matter",
-        "icon": {
-          "dark": "/assets/icons/frontmatter-small-dark.svg",
-          "light": "/assets/icons/frontmatter-small-light.svg"
-        }
+        "icon": "$(fm-logo)"
       },
       {
         "command": "frontMatter.dashboard.data",
         "title": "%command.frontMatter.dashboard.data%",
         "category": "Front Matter",
-        "icon": {
-          "dark": "/assets/icons/frontmatter-small-dark.svg",
-          "light": "/assets/icons/frontmatter-small-light.svg"
-        }
+        "icon": "$(fm-logo)"
       },
       {
         "command": "frontMatter.dashboard.media",
         "title": "%command.frontMatter.dashboard.media%",
         "category": "Front Matter",
-        "icon": {
-          "dark": "/assets/icons/frontmatter-small-dark.svg",
-          "light": "/assets/icons/frontmatter-small-light.svg"
-        }
+        "icon": "$(fm-logo)"
       },
       {
         "command": "frontMatter.dashboard.snippets",
         "title": "%command.frontMatter.dashboard.snippets%",
         "category": "Front Matter",
-        "icon": {
-          "dark": "/assets/icons/frontmatter-small-dark.svg",
-          "light": "/assets/icons/frontmatter-small-light.svg"
-        }
+        "icon": "$(fm-logo)"
       },
       {
         "command": "frontMatter.dashboard.taxonomy",
         "title": "%command.frontMatter.dashboard.taxonomy%",
         "category": "Front Matter",
-        "icon": {
-          "dark": "/assets/icons/frontmatter-small-dark.svg",
-          "light": "/assets/icons/frontmatter-small-light.svg"
-        }
+        "icon": "$(fm-logo)"
       },
       {
         "command": "frontMatter.markup.orderedlist",
@@ -2122,15 +2131,12 @@
         "category": "Front Matter"
       }
     ],
-    "submenus": [
-      {
-        "id": "frontmatter.submenu",
-        "label": "Front Matter"
-      }
-    ],
+    "submenus": [{
+      "id": "frontmatter.submenu",
+      "label": "Front Matter"
+    }],
     "menus": {
-      "editor/title": [
-        {
+      "editor/title": [{
           "command": "frontMatter.markup.heading",
           "group": "navigation@-133",
           "when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
@@ -2211,14 +2217,11 @@
           "when": "resourceFilename == 'frontmatter.json'"
         }
       ],
-      "explorer/context": [
-        {
-          "submenu": "frontmatter.submenu",
-          "group": "frontmatter@1"
-        }
-      ],
-      "frontmatter.submenu": [
-        {
+      "explorer/context": [{
+        "submenu": "frontmatter.submenu",
+        "group": "frontmatter@1"
+      }],
+      "frontmatter.submenu": [{
           "command": "frontMatter.createFromTemplate",
           "when": "explorerResourceIsFolder",
           "group": "frontmatter@1"
@@ -2234,8 +2237,7 @@
           "group": "frontmatter@3"
         }
       ],
-      "commandPalette": [
-        {
+      "commandPalette": [{
           "command": "frontMatter.init",
           "when": "frontMatterCanInit"
         },
@@ -2380,8 +2382,7 @@
           "when": "frontMatter:file:isValid == true"
         }
       ],
-      "view/title": [
-        {
+      "view/title": [{
           "command": "frontMatter.chatbot",
           "group": "navigation@0",
           "when": "view == frontMatter.explorer"
@@ -2403,7 +2404,8 @@
         },
         {
           "command": "frontMatter.settings.refresh",
-          "group": "navigation@4"
+          "group": "navigation@4",
+          "when": "view == frontMatter.explorer"
         },
         {
           "command": "frontMatter.dashboard",
@@ -2412,57 +2414,52 @@
         }
       ]
     },
-    "grammars": [
-      {
-        "path": "./syntaxes/hugo.tmLanguage.json",
-        "scopeName": "frontmatter.markdown.hugo",
-        "injectTo": [
-          "text.html.markdown"
-        ]
-      }
-    ],
-    "walkthroughs": [
-      {
-        "id": "frontmatter.welcome",
-        "title": "Get started with Front Matter",
-        "description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
-        "steps": [
-          {
-            "id": "frontmatter.welcome.init",
-            "title": "Get started",
-            "description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
-            "media": {
-              "markdown": "assets/walkthrough/get-started.md"
-            },
-            "completionEvents": [
-              "onContext:frontMatterInitialized"
-            ]
+    "grammars": [{
+      "path": "./syntaxes/hugo.tmLanguage.json",
+      "scopeName": "frontmatter.markdown.hugo",
+      "injectTo": [
+        "text.html.markdown"
+      ]
+    }],
+    "walkthroughs": [{
+      "id": "frontmatter.welcome",
+      "title": "Get started with Front Matter",
+      "description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
+      "steps": [{
+          "id": "frontmatter.welcome.init",
+          "title": "Get started",
+          "description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
+          "media": {
+            "markdown": "assets/walkthrough/get-started.md"
           },
-          {
-            "id": "frontmatter.welcome.documentation",
-            "title": "Documentation",
-            "description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
-            "media": {
-              "markdown": "assets/walkthrough/documentation.md"
-            },
-            "completionEvents": [
-              "onLink:https://frontmatter.codes/docs"
-            ]
+          "completionEvents": [
+            "onContext:frontMatterInitialized"
+          ]
+        },
+        {
+          "id": "frontmatter.welcome.documentation",
+          "title": "Documentation",
+          "description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
+          "media": {
+            "markdown": "assets/walkthrough/documentation.md"
           },
-          {
-            "id": "frontmatter.welcome.supporter",
-            "title": "Support the project",
-            "description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
-            "media": {
-              "markdown": "assets/walkthrough/support-the-project.md"
-            },
-            "completionEvents": [
-              "onLink:https://github.com/sponsors/estruyf"
-            ]
-          }
-        ]
-      }
-    ]
+          "completionEvents": [
+            "onLink:https://frontmatter.codes/docs"
+          ]
+        },
+        {
+          "id": "frontmatter.welcome.supporter",
+          "title": "Support the project",
+          "description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
+          "media": {
+            "markdown": "assets/walkthrough/support-the-project.md"
+          },
+          "completionEvents": [
+            "onLink:https://github.com/sponsors/estruyf"
+          ]
+        }
+      ]
+    }]
   },
   "scripts": {
     "dev:ext": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
@@ -2522,7 +2519,7 @@
     "@typescript-eslint/parser": "^5.50.0",
     "@vscode/codicons": "0.0.20",
     "@vscode/l10n": "^0.0.14",
-    "@vscode/webview-ui-toolkit": "^0.9.3",
+    "@vscode/webview-ui-toolkit": "^1.2.2",
     "@webpack-cli/serve": "^1.7.0",
     "ajv": "^8.12.0",
     "array-move": "^4.0.0",
@@ -2532,6 +2529,7 @@
     "cheerio": "1.0.0-rc.12",
     "css-loader": "5.2.7",
     "date-fns": "2.23.0",
+    "dotenv": "^16.3.1",
     "downshift": "6.0.6",
     "eslint": "^8.33.0",
     "fuse.js": "6.5.3",
@@ -2591,10 +2589,11 @@
     "webpack-bundle-analyzer": "^4.7.0",
     "webpack-cli": "^4.10.0",
     "webpack-dev-server": "^4.11.1",
+    "webpack-ignore-dynamic-require": "^1.0.0",
     "yaml": "^2.2.1",
     "yawn-yaml": "^1.5.0"
   },
   "vsce": {
     "dependencies": false
   }
-}
+}
\ No newline at end of file
diff --git a/package.nls.de.json b/package.nls.de.json
index a0fbff97..b337f775 100644
--- a/package.nls.de.json
+++ b/package.nls.de.json
@@ -239,8 +239,11 @@
   "setting.frontMatter.dashboard.mediaSnippet.deprecationMessage": "Diese Einstellung ist veraltet und wird in der nächsten Hauptversion entfernt. Bitte definieren Sie Ihr Medien-Snippet in der `frontMatter.content.snippet` Einstellung.",
   "setting.frontMatter.taxonomy.dateField.deprecationMessage": "Diese Einstellung ist veraltet und wird in der nächsten Hauptversion entfernt. Bitte verwenden Sie stattdessen die neuen `isPublishDate`-Einstellungen in den Datumsfeldern Ihrer Content-Typen.",
   "setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "Diese Einstellung ist veraltet und wird in der nächsten Hauptversion entfernt. Bitte verwenden Sie stattdessen die neuen `isModifiedDate`-Einstellungen in den Datumsfeldern Ihrer Content-Typen.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "🚧: Specify the name of the custom field type to use.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "🚧: Specify if the empty values should be cleared.",
-  "setting.frontMatter.website.host.markdownDescription": "🚧: Specify the host URL of your website. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
-  "command.frontMatter.settings.refresh": "🚧: Refresh Front Matter Settings"
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "Geben Sie den Namen des zu verwendenden benutzerdefinierten Feldtyps an.",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "Geben Sie an, ob die leeren Werte gelöscht werden sollen.",
+  "setting.frontMatter.website.host.markdownDescription": "Geben Sie die Host-URL Ihrer Website an. [Überprüfen Sie die Dokumente] (https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
+  "command.frontMatter.settings.refresh": "Aktualisieren Sie die Einstellungen für Frontmatter",
+  "setting.frontMatter.config.dynamicFilePath.markdownDescription": "Geben Sie den Pfad zur dynamischen Konfigurationsdatei an (z. B. [[workspace]]/config.js). [Überprüfen Sie die Dokumente] (https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)",
+  "setting.frontMatter.content.pageFolders.items.properties.disableCreation.description": "Deaktivieren Sie die Erstellung neuer Inhalte im Ordner.",
+  "setting.frontMatter.custom.scripts.items.properties.contentTypes.description": "Definieren Sie die Inhaltstypen, für die das Skript verwendet werden soll. Wenn keine definiert sind, ist sie für alle Typen verfügbar."
 }
\ No newline at end of file
diff --git a/package.nls.ja.json b/package.nls.ja.json
index e1ee8fcd..f288cdae 100644
--- a/package.nls.ja.json
+++ b/package.nls.ja.json
@@ -50,8 +50,8 @@
   "command.frontMatter.cache.clear": "キャッシュをクリア",
   "settings.configuration.title": "Front Matter: チームで作業する場合はfrontmatter.jsonで設定してください。",
   "setting.frontMatter.projects.markdownDescription": "Front Matter CMSを利用するプロジェクトを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.projects)",
-  "setting.frontMatter.projects.items.properties.name.markdownDescription": "🚧: Specify the name of the project.",
-  "setting.frontMatter.projects.items.properties.default.markdownDescription": "🚧: Specify if this project is the default project to load.",
+  "setting.frontMatter.projects.items.properties.name.markdownDescription": "プロジェクトの名前を指定します。",
+  "setting.frontMatter.projects.items.properties.default.markdownDescription": "このプロジェクトを読み込む既定のプロジェクトにするかどうかを指定します。",
   "setting.frontMatter.sponsors.ai.enabled.markdownDescription": "AIによる提案を利用します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.sponsors.ai.enabled)",
   "setting.frontMatter.extensibility.scripts.markdownDescription": "Front Matter CMSで読み込むスクリプトのリストを指定します。. [ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.extensibility.scripts)",
   "setting.frontMatter.experimental.markdownDescription": "実験的な機能をオンにします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.experimental)",
@@ -60,80 +60,80 @@
   "setting.frontMatter.content.defaultFileType.markdownDescription": "新しい記事を作成する際の既定のファイル形式を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.defaultfiletype)",
   "setting.frontMatter.content.defaultSorting.markdownDescription": "ダッシュボード上に表示される記事一覧の既定の並び順を設定します。Enum(列挙型)や任意のIDを指定してください。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.defaultsorting)",
   "setting.frontMatter.content.draftField.markdownDescription": "記事の下書きステータスを管理するフィールドを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.draftfield)",
-  "setting.frontMatter.content.draftField.properties.type.description": "🚧: Type of the draft field you want to use",
-  "setting.frontMatter.content.draftField.properties.name.description": "🚧: Name of the field to use",
-  "setting.frontMatter.content.draftField.properties.invert.description": "🚧: By default the draft field is set to true when the content is a draft. Set this to true to set it to false.",
-  "setting.frontMatter.content.draftField.properties.choices.description": "🚧: List of choices for the field",
+  "setting.frontMatter.content.draftField.properties.type.description": "使用する下書きフィールドの種類",
+  "setting.frontMatter.content.draftField.properties.name.description": "使用するフィールドの名前",
+  "setting.frontMatter.content.draftField.properties.invert.description": "既定では、コンテンツが下書きの場合、下書きフィールドは true に設定されます。これを true に設定すると、false に設定されます。",
+  "setting.frontMatter.content.draftField.properties.choices.description": "フィールドの選択肢のリスト",
   "setting.frontMatter.content.fmHighlight.markdownDescription": "Markdownファイル内のfront matterをハイライトします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.fmhighlight)",
   "setting.frontMatter.content.hideFm.markdownDescription": "Markdownファイル内のfront matterを非表示にします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.hidefm)",
   "setting.frontMatter.content.hideFmMessage.markdownDescription": "front matterが非表示の際に、編集画面に表示するメッセージを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.hidefmmessage)",
   "setting.frontMatter.content.pageFolders.markdownDescription": "フォルダーを配列で定義して、この拡張機能が記事を取得したり新しい記事を作成できるようにします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.pagefolders)",
-  "setting.frontMatter.content.pageFolders.items.properties.title.description": "🚧: Name of the folder",
-  "setting.frontMatter.content.pageFolders.items.properties.path.description": "🚧: Path of the folder",
-  "setting.frontMatter.content.pageFolders.items.properties.excludeSubdir.description": "🚧: Exclude sub-directories",
-  "setting.frontMatter.content.pageFolders.items.properties.previewPath.description": "🚧: Defines a custom preview path for the folder.",
-  "setting.frontMatter.content.pageFolders.items.properties.filePrefix.description": "🚧: Defines a prefix for the file name.",
-  "setting.frontMatter.content.pageFolders.items.properties.contentTypes.description": "🚧: Defines which content types can be used for the current location. If not defined, all content types will be available.",
+  "setting.frontMatter.content.pageFolders.items.properties.title.description": "フォルダの名前",
+  "setting.frontMatter.content.pageFolders.items.properties.path.description": "フォルダのパス",
+  "setting.frontMatter.content.pageFolders.items.properties.excludeSubdir.description": "サブディレクトリを除外する",
+  "setting.frontMatter.content.pageFolders.items.properties.previewPath.description": "フォルダーのカスタム プレビュー パスを定義します。",
+  "setting.frontMatter.content.pageFolders.items.properties.filePrefix.description": "ファイル名のプレフィックスを定義します。",
+  "setting.frontMatter.content.pageFolders.items.properties.contentTypes.description": "現在の場所に使用できるコンテンツ タイプを定義します。定義しない場合は、すべてのコンテンツ タイプを使用できます。",
   "setting.frontMatter.content.placeholders.markdownDescription": "記事タイプとテンプレートで使用するプレースホルダーを配列で定義して、記事のfront matterを自動で入力できるようにします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.placeholders)",
-  "setting.frontMatter.content.placeholders.items.properties.id.description": "🚧: ID of the placeholder, in your content type or template, use it as follows: {{placeholder}}",
-  "setting.frontMatter.content.placeholders.items.properties.value.description": "🚧: The placeholder its value",
-  "setting.frontMatter.content.placeholders.items.properties.script.description": "🚧: The script to execute to get the value of the placeholder",
+  "setting.frontMatter.content.placeholders.items.properties.id.description": "プレースホルダーの ID をコンテンツ タイプまたはテンプレートで、次のように使用します: {{placeholder}}",
+  "setting.frontMatter.content.placeholders.items.properties.value.description": "プレースホルダーの値",
+  "setting.frontMatter.content.placeholders.items.properties.script.description": "プレースホルダーの値を取得するために実行するスクリプト",
   "setting.frontMatter.content.publicFolder.markdownDescription": "アセットが保存されているフォルダーを設定します。例えば、Hugoでは`static`フォルダーです。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.publicfolder)",
   "setting.frontMatter.content.publicFolder.properties.path.description": "アセットフォルダーのパスを指定します。",
   "setting.frontMatter.content.publicFolder.properties.relative.description": "メディアファイルへのパスがコンテンツファイルに対して相対的であるかを定義します。",
   "setting.frontMatter.snippets.wrapper.enabled.markdownDescription": "スニペット挿入時にコメントでラップします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.snippets.wrapper.enabled)",
   "setting.frontMatter.content.snippets.markdownDescription": "記事中に使用するスニペットを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.snippets)",
   "setting.frontMatter.content.sorting.markdownDescription": "ダッシュボード上での記事の並べ替えオプションを追加します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.sorting)",
-  "setting.frontMatter.content.sorting.items.properties.id.description": "🚧: The ID of the sorting option. This will be used for the storing the last used sorting option or the default option.",
-  "setting.frontMatter.content.sorting.items.properties.title.description": "🚧: Name of the sorting label",
-  "setting.frontMatter.content.sorting.items.properties.name.description": "🚧: Name of the metadata field to sort by",
-  "setting.frontMatter.content.sorting.items.properties.order.description": "🚧: Order of the sorting",
-  "setting.frontMatter.content.sorting.items.properties.type.description": "🚧: Type of the field value",
+  "setting.frontMatter.content.sorting.items.properties.id.description": "並べ替えオプションの ID。これは、最後に使用した並べ替えオプションまたは既定のオプションを格納するために使用されます。",
+  "setting.frontMatter.content.sorting.items.properties.title.description": "並べ替えラベルの名前",
+  "setting.frontMatter.content.sorting.items.properties.name.description": "並べ替えの基準となるメタデータ フィールドの名前",
+  "setting.frontMatter.content.sorting.items.properties.order.description": "ソートの順序",
+  "setting.frontMatter.content.sorting.items.properties.type.description": "フィールド値の型",
   "setting.frontMatter.content.supportedFileTypes.markdownDescription": "Front Matterでサポートされるファイル形式を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.supportedfiletypes)",
   "setting.frontMatter.content.wysiwyg.markdownDescription": "What You See, Is What You Get(WYSIWYG)Markdownコントロールを有効にします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.wysiwyg)",
   "setting.frontMatter.custom.scripts.markdownDescription": "実行するNode.jsスクリプトのパスを指定します。現在のファイルのパスが引数として渡されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.custom.scripts)",
-  "setting.frontMatter.custom.scripts.items.properties.id.description": "🚧: ID of the script.",
-  "setting.frontMatter.custom.scripts.items.properties.title.description": "🚧: Title you want to give to your script. Will be shown as the title of the button.",
-  "setting.frontMatter.custom.scripts.items.properties.script.description": "🚧: Path to the script to execute",
-  "setting.frontMatter.custom.scripts.items.properties.nodeBin.description": "🚧: Path to the node executable. This is required when using NVM, so that there is no confusion of which node version to use. (deprecated: use the command property instead)",
-  "setting.frontMatter.custom.scripts.items.properties.bulk.description": "🚧: Run the script for all content files",
-  "setting.frontMatter.custom.scripts.items.properties.output.description": "🚧: Define where you want to output your script output. Default is a notification, but you can specify to show it in an editor panel.",
-  "setting.frontMatter.custom.scripts.items.properties.outputType.description": "🚧: The type of output for the editor panel. Can be used to change it to 'markdown' for example",
-  "setting.frontMatter.custom.scripts.items.properties.type.description": "🚧: The type for which the script will be used.",
-  "setting.frontMatter.custom.scripts.items.properties.command.description": "🚧: The type of script you want to execute.",
-  "setting.frontMatter.custom.scripts.items.properties.hidden.description": "🚧: Hide the action from the UI",
-  "setting.frontMatter.custom.scripts.items.properties.environments.items.properties.type.description": "🚧: The environment type for which the script needs to be used",
-  "setting.frontMatter.custom.scripts.items.properties.environments.items.properties.script.description": "🚧: Path to the script to execute",
+  "setting.frontMatter.custom.scripts.items.properties.id.description": "スクリプトの ID。",
+  "setting.frontMatter.custom.scripts.items.properties.title.description": "スクリプトに付けるタイトル。ボタンのタイトルとして表示されます。",
+  "setting.frontMatter.custom.scripts.items.properties.script.description": "実行するスクリプトへのパス",
+  "setting.frontMatter.custom.scripts.items.properties.nodeBin.description": "ノード実行可能ファイルへのパス。これは、使用するノードのバージョンが混同されないように、NVM を使用するときに必要です。(非推奨: 代わりにコマンド プロパティを使用してください)",
+  "setting.frontMatter.custom.scripts.items.properties.bulk.description": "すべてのコンテンツ ファイルに対してスクリプトを実行する",
+  "setting.frontMatter.custom.scripts.items.properties.output.description": "スクリプト出力を出力する場所を定義します。デフォルトは通知ですが、エディターパネルに表示するように指定できます。",
+  "setting.frontMatter.custom.scripts.items.properties.outputType.description": "エディター・パネルの出力のタイプ。たとえば、「マークダウン」に変更するために使用できます",
+  "setting.frontMatter.custom.scripts.items.properties.type.description": "スクリプトが使用される型。",
+  "setting.frontMatter.custom.scripts.items.properties.command.description": "実行するスクリプトの種類。",
+  "setting.frontMatter.custom.scripts.items.properties.hidden.description": "UI からアクションを非表示にする",
+  "setting.frontMatter.custom.scripts.items.properties.environments.items.properties.type.description": "スクリプトを使用する必要がある環境タイプ",
+  "setting.frontMatter.custom.scripts.items.properties.environments.items.properties.script.description": "実行するスクリプトへのパス",
   "setting.frontMatter.dashboard.content.pagination.markdownDescription": "ページネーションの有効/無効を設定します。ページ数は最大52まで設定できます。規定値は`16`です。ページ分割を無効にするには`false`を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.content.pagination)",
   "setting.frontMatter.dashboard.content.cardTags.markdownDescription": "記事一覧をカード型で表示する際、どのメタデータフィールドをタグとして使うかを指定します。空欄またはnull値の場合、タグは表示されなくなります。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.content.cardtags)",
   "setting.frontMatter.dashboard.content.card.fields.state.markdownDescription": "記事一覧をカード型で表示する際、下書き・公開済みのステータスを表示します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.state)",
   "setting.frontMatter.dashboard.content.card.fields.date.markdownDescription": "記事一覧をカード型で表示する際、日付を表示します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.date)",
   "setting.frontMatter.dashboard.content.card.fields.description.markdownDescription": "記事一覧をカード型で表示する際、どのメタデータフィールドをディスクリプションとして使うかを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.description)",
   "setting.frontMatter.dashboard.content.card.fields.title.markdownDescription": "記事一覧をカード型で表示する際、どのメタデータフィールドをタイトルとして使うかを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.title)",
-  "setting.frontMatter.dashboard.mediaSnippet.markdownDescription": "🚧: Specify the a snippet for your custom media insert markup. [ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.mediasnippet)",
+  "setting.frontMatter.dashboard.mediaSnippet.markdownDescription": "カスタムメディア挿入マークアップのスニペットを指定します。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.mediasnippet)",
   "setting.frontMatter.dashboard.mediaSnippet.items.description": "スニペット内で `{mediaUrl}`, `{caption}`, `{alt}`, `{filename}`, `{mediaHeight}`, `{mediaWidth}` のプレースホルダーを使用して、メディア情報を自動的に挿入します。",
   "setting.frontMatter.dashboard.openOnStart.markdownDescription": "VS Codeの起動時にダッシュボードを表示します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.openonstart)",
   "setting.frontMatter.data.files.markdownDescription": "ウェブサイトに使用するデータのファイルを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.data.files)",
-  "setting.frontMatter.data.files.items.properties.id.description": "🚧: Your unique ID you want to use for your data file.",
-  "setting.frontMatter.data.files.items.properties.title.description": "🚧: Title you want to give to your data file.",
-  "setting.frontMatter.data.files.items.properties.labelField.description": "🚧: The field you want to use as label for your data entries.",
-  "setting.frontMatter.data.files.items.properties.file.description": "🚧: Path to the file to load. Only JSON or YAML files are supported.",
-  "setting.frontMatter.data.files.items.properties.fileType.description": "🚧: Defines how you want to parse the file. JSON is the default.",
-  "setting.frontMatter.data.files.items.properties.schema.description": "🚧: The JSON schema for your data which will be used to render the data form.",
-  "setting.frontMatter.data.files.items.properties.schema.properties.title.description": "🚧: Title of the form.",
-  "setting.frontMatter.data.files.items.properties.schema.properties.type.description": "🚧: Defines the type of the form. Default is 'object'.",
-  "setting.frontMatter.data.files.items.properties.schema.properties.required.description": "🚧: Defines the required fields for the form.",
-  "setting.frontMatter.data.files.items.properties.schema.properties.properties.description": "🚧: Defines the fields of the form.",
-  "setting.frontMatter.data.files.items.properties.type.description": "🚧: If you are using data types, you can specify your type ID.",
-  "setting.frontMatter.data.files.items.properties.singleEntry.description": "🚧: If you want to use a single entry for your data file.",
+  "setting.frontMatter.data.files.items.properties.id.description": "データ ファイルに使用する一意の ID。",
+  "setting.frontMatter.data.files.items.properties.title.description": "データ ファイルに付けるタイトル。",
+  "setting.frontMatter.data.files.items.properties.labelField.description": "データエントリのラベルとして使用するフィールド。",
+  "setting.frontMatter.data.files.items.properties.file.description": "読み込むファイルへのパス。JSON または YAML ファイルのみがサポートされています。",
+  "setting.frontMatter.data.files.items.properties.fileType.description": "ファイルの解析方法を定義します。JSON がデフォルトです。",
+  "setting.frontMatter.data.files.items.properties.schema.description": "データ フォームのレンダリングに使用されるデータの JSON スキーマ。",
+  "setting.frontMatter.data.files.items.properties.schema.properties.title.description": "フォームのタイトル。",
+  "setting.frontMatter.data.files.items.properties.schema.properties.type.description": "フォームの種類を定義します。デフォルトは 'オブジェクト' です。",
+  "setting.frontMatter.data.files.items.properties.schema.properties.required.description": "フォームの必須フィールドを定義します。",
+  "setting.frontMatter.data.files.items.properties.schema.properties.properties.description": "フォームのフィールドを定義します。",
+  "setting.frontMatter.data.files.items.properties.type.description": "データ型を使用している場合は、型 ID を指定できます。",
+  "setting.frontMatter.data.files.items.properties.singleEntry.description": "データ ファイルに 1 つのエントリを使用する場合。",
   "setting.frontMatter.data.folders.markdownDescription": "ウェブサイトに使用するデータのフォルダーを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.data.folders)",
-  "setting.frontMatter.data.folders.items.properties.id.description": "🚧: Your unique ID you want to use for your data folder.",
-  "setting.frontMatter.data.folders.items.properties.labelField.description": "🚧: The field you want to use as label for your data entries.",
-  "setting.frontMatter.data.folders.items.properties.path.description": "🚧: Path to the folder to load files.",
-  "setting.frontMatter.data.folders.items.properties.type.description": "🚧: If you are using data types, you can specify your type ID.",
-  "setting.frontMatter.data.folders.items.properties.singleEntry.description": "🚧: If you want to use a single entry for your data files in the folder.",
+  "setting.frontMatter.data.folders.items.properties.id.description": "データ フォルダーに使用する一意の ID。",
+  "setting.frontMatter.data.folders.items.properties.labelField.description": "データエントリのラベルとして使用するフィールド。",
+  "setting.frontMatter.data.folders.items.properties.path.description": "ファイルを読み込むフォルダーへのパス。",
+  "setting.frontMatter.data.folders.items.properties.type.description": "データ型を使用している場合は、型 ID を指定できます。",
+  "setting.frontMatter.data.folders.items.properties.singleEntry.description": "フォルダー内のデータ ファイルに 1 つのエントリを使用する場合。",
   "setting.frontMatter.data.types.markdownDescription": "データタイプを指定します。これらのタイプは、データファイルで使用できます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.data.types)",
-  "setting.frontMatter.data.types.items.properties.id.description": "🚧: Your unique ID you want to use for your data type.",
+  "setting.frontMatter.data.types.items.properties.id.description": "データ型に使用する一意の ID。",
   "setting.frontMatter.file.preserveCasing.markdownDescription": "タイトルからファイル名の大文字と小文字を区別します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.file.preservecasing)",
   "setting.frontMatter.framework.id.markdownDescription": "ウェブサイトに使用している静的サイトジェネレーターまたはフレームワークのIDを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.framework.id)",
   "setting.frontMatter.framework.startCommand.markdownDescription": "静的サイト・ジェネレーターまたはフレームワークを起動させるコマンドを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.framework.startcommand)",
@@ -145,8 +145,8 @@
   "setting.frontMatter.git.submodule.folder.markdownDescription": "コンテンツのサブモジュールフォルダーを指定します。複数のサブモジュールを使用する場合に便利です。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.git.submodule.folder)",
   "setting.frontMatter.global.activeMode.markdownDescription": "Front Matterで有効なモードを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.activemode)",
   "setting.frontMatter.global.modes.markdownDescription": "Front Matterで利用するモードを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.modes)",
-  "setting.frontMatter.global.modes.items.properties.id.description": "🚧: The ID of your mode.",
-  "setting.frontMatter.global.modes.items.properties.features.description": "🚧: The features you want to use for your mode.",
+  "setting.frontMatter.global.modes.items.properties.id.description": "モードの ID。",
+  "setting.frontMatter.global.modes.items.properties.features.description": "モードに使用する機能。",
   "setting.frontMatter.global.notifications.markdownDescription": "表示したい通知を設定します。既定では全ての通知が表示されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.notifications)",
   "setting.frontMatter.global.disabledNotificaitons.markdownDescription": "表示しない通知を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
   "setting.frontMatter.media.defaultSorting.markdownDescription": "ダッシュボードのメディア一覧での既定の並び順を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.media.defaultsorting)",
@@ -161,66 +161,66 @@
   "setting.frontMatter.taxonomy.commaSeparatedFields.items.description": "コンマ区切りの配列として使用するフィールドの名前。",
   "setting.frontMatter.taxonomy.contentTypes.markdownDescription": "記事・ページ・その他で利用したい記事タイプを設定します。front matterで正しく`type`が設定されていることを確認してください。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.contenttypes)",
   "setting.frontMatter.taxonomy.contentTypes.items.description": "Front Matterで使用するコンテンツタイプを定義します。",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.name.description": "🚧: Define the type of field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fileType.description": "🚧: Specifies the type of content you want to create.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.description": "🚧: Define the fields of the content type",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.name.description": "フィールドの種類を定義する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fileType.description": "作成するコンテンツの種類を指定します。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.description": "コンテンツ タイプのフィールドを定義する",
   "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.description": "Front Matterで使用するコンテンツタイプを定義します。",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.type.description": "🚧: Define the type of field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.name.description": "🚧: Name of the field to use",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.title.description": "🚧: Title to show in the UI",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.description.description": "🚧: Description to show in the UI",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.default.description": "🚧: Default value",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.choices.description": "🚧: Define your choices",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.choices.items.properties.id.description": "🚧: The choice ID",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.choices.items.properties.title.description": "🚧: The choice title",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.single.description": "🚧: Is a single line field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.wysiwyg.description": "🚧: Is a WYSIWYG field (HTML output)",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.multiple.description": "🚧: Do you allow to select multiple values?",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPreviewImage.description": "🚧: Specify if the image field can be used as preview. Be aware, you can only have one preview image per content type.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.hidden.description": "🚧: Do you want to hide the field from the metadata section?",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description": "🚧: The ID of your taxonomy field. It cannot contain the \"tags\" or \"categories\" value.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fileExtensions.description": "🚧: Specify the file extensions to allow for the file picker",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fieldGroup.description": "🚧: The ID(s) of your field group(s) defined in the `frontMatter.taxonomy.fieldGroups` setting",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataType.description": "🚧: The ID(s) of your data type(s) defined in the `frontMatter.data.types` setting",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.description": "🚧: Specify the options for the number field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.isDecimal.description": "🚧: Specify if the number is a decimal",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.min.description": "🚧: The minimum value",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.max.description": "🚧: The maximum value",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.step.description": "🚧: The step value",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyLimit.description": "🚧: Limit the number of taxonomies to select. Set to 0 to allow unlimited.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPublishDate.description": "🚧: Specify if the field is the publish date field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isModifiedDate.description": "🚧: Specify if the field is the modified date field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileId.description": "🚧: Specify the ID of the data file to use for this field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileKey.description": "🚧: Specify the key of the data file to use for this field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileValue.description": "🚧: Specify the property name that will be used to show the value for the field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.editable.description": "🚧: Specify if the field is editable",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.encodeEmoji.description": "🚧: Specify if the field should encode emoji",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dateFormat.description": "🚧: Specify the date format to use",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.required.description": "🚧: Specify if the field is required",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeName.description": "🚧: Specify the content type name to filter content for the contentRelationship field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeValue.description": "🚧: Specify the value to insert for the contentRelationship field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.description": "🚧: Specify the conditions to show the field",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.fieldRef.description": "🚧: The field ID to use",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.operator.description": "🚧: The operator to use",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.value.description": "🚧: The value to compare",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.caseSensitive.description": "🚧: Specify if the comparison is case sensitive. Default: true",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.pageBundle.description": "🚧: Specify if you want to create a folder when creating new content.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.previewPath.description": "🚧: Defines a custom preview path for the content type.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.template.description": "🚧: An optional template that can be used for creating new content.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.postScript.description": "🚧: An optional post script that can be used after new content creation.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.filePrefix.description": "🚧: Defines a prefix for the file name.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.defaultFileName.description": "🚧: Default file name to use when creating new content.",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.type.description": "フィールドの種類を定義する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.name.description": "使用するフィールドの名前",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.title.description": "UI に表示するタイトル",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.description.description": "UI に表示する説明",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.default.description": "既定値",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.choices.description": "選択肢を定義する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.choices.items.properties.id.description": "選択肢 ID",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.choices.items.properties.title.description": "選択肢のタイトル",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.single.description": "単一行フィールドである",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.wysiwyg.description": "WYSIWYG フィールド (HTML 出力) である",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.multiple.description": "複数の値を選択できますか?",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPreviewImage.description": "画像フィールドをプレビューとして使用できるかどうかを指定します。コンテンツ タイプごとに使用できるプレビュー画像は 1 つだけです。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.hidden.description": "メタデータ セクションからフィールドを非表示にしますか?",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description": "分類フィールドの ID。「タグ」または「カテゴリ」の値を含めることはできません。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fileExtensions.description": "ファイル ピッカーで許可するファイル拡張子を指定する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fieldGroup.description": "'frontMatter.taxonomy.fieldGroups' 設定で定義されているフィールドグループの ID",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataType.description": "'frontMatter.data.types' 設定で定義されているデータ型の ID",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.description": "数値フィールドのオプションを指定する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.isDecimal.description": "数値が 10 進数かどうかを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.min.description": "最小値",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.max.description": "最大値",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.step.description": "ステップ値",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyLimit.description": "選択する分類の数を制限します。無制限を許可するには 0 に設定します。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPublishDate.description": "フィールドが公開日フィールドであるかどうかを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isModifiedDate.description": "フィールドが変更日フィールドであるかどうかを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileId.description": "このフィールドに使用するデータファイルのIDを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileKey.description": "このフィールドに使用するデータファイルのキーを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileValue.description": "フィールドの値を表示するために使用するプロパティ名を指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.editable.description": "フィールドが編集可能かどうかを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.encodeEmoji.description": "フィールドが絵文字をエンコードするかどうかを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dateFormat.description": "使用する日付形式を指定する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.required.description": "フィールドが必須かどうかを指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeName.description": "コンテンツ タイプ名を指定して、contentRelationship フィールドのコンテンツをフィルター処理します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeValue.description": "コンテンツリレーションシップフィールドに挿入する値を指定します",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.description": "フィールドを表示する条件を指定する",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.fieldRef.description": "使用するフィールド ID",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.operator.description": "使用する演算子",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.value.description": "比較する値",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.caseSensitive.description": "比較で大文字と小文字を区別するかどうかを指定します。デフォルト: 真",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.pageBundle.description": "新しいコンテンツを作成するときにフォルダーを作成するかどうかを指定します。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.previewPath.description": "コンテンツ タイプのカスタム プレビュー パスを定義します。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.template.description": "新しいコンテンツの作成に使用できるオプションのテンプレート。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.postScript.description": "新しいコンテンツの作成後に使用できるオプションのポストスクリプト。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.filePrefix.description": "ファイル名のプレフィックスを定義します。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.defaultFileName.description": "新しいコンテンツを作成するときに使用する既定のファイル名。",
   "setting.frontMatter.taxonomy.customTaxonomy.markdownDescription": "カスタムタクソノミーのフィールドデータを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.tags)",
-  "setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description": "🚧: ID for your taxonomy field. It cannot contain the \"tags\" or \"categories\" value.",
-  "setting.frontMatter.taxonomy.customTaxonomy.items.properties.options.description": "🚧: Options from which you can pick.",
-  "setting.frontMatter.taxonomy.dateField.markdownDescription": "🚧: This setting is used to define the publishing date field of your articles. [ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.datefield)",
+  "setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description": "分類フィールドの ID。「タグ」または「カテゴリ」の値を含めることはできません。",
+  "setting.frontMatter.taxonomy.customTaxonomy.items.properties.options.description": "選択できるオプション。",
+  "setting.frontMatter.taxonomy.dateField.markdownDescription": "この設定は、記事の公開日フィールドを定義するために使用されます。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.datefield)",
   "setting.frontMatter.taxonomy.dateFormat.markdownDescription": "記事の日付フォーマットを指定します。詳しくは[date-fns formatting](https://date-fns.org/v2.0.1/docs/format)を確認してください。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.dateformat)",
   "setting.frontMatter.taxonomy.fieldGroups.markdownDescription": "ブロックフィールドで使用したいフィールドグループを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.fieldgroups)",
-  "setting.frontMatter.taxonomy.fieldGroups.items.properties.id.description": "🚧: The name of the field group",
-  "setting.frontMatter.taxonomy.fieldGroups.items.properties.labelField.description": "🚧: The name of the field to be used as display value",
+  "setting.frontMatter.taxonomy.fieldGroups.items.properties.id.description": "フィールドグループの名前",
+  "setting.frontMatter.taxonomy.fieldGroups.items.properties.labelField.description": "表示値として使用するフィールドの名前",
   "setting.frontMatter.taxonomy.frontMatterType.markdownDescription": "front matterの形式を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.frontmattertype)",
   "setting.frontMatter.taxonomy.indentArrays.markdownDescription": "front matterメタデータが配列の場合はインデント(字下げ)させます。規定値はtrueです。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.indentarrays)",
-  "setting.frontMatter.taxonomy.modifiedField.markdownDescription": "🚧: This setting is used to define the modified date field of your articles. [ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.modifiedfield)",
+  "setting.frontMatter.taxonomy.modifiedField.markdownDescription": "この設定は、記事の変更日フィールドを定義するために使用されます。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.modifiedfield)",
   "setting.frontMatter.taxonomy.noPropertyValueQuotes.markdownDescription": "引用符を付与しないメタデータを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.nopropertyvaluequotes)",
   "setting.frontMatter.taxonomy.noPropertyValueQuotes.items.description": "引用符を削除したいプロパティの名前。",
   "setting.frontMatter.taxonomy.seoContentLengh.markdownDescription": "最適な記事の長さを指定します。2021年のSEOでは、1,760語から2,400語の間が最も理想的とされています。(-1に設定するとオフになります。)[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.seocontentlengh)",
@@ -236,12 +236,15 @@
   "setting.frontMatter.templates.enabled.markdownDescription": "テンプレート機能を利用します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.templates.enabled)",
   "setting.frontMatter.templates.folder.markdownDescription": "テンプレートを保存するフォルダーを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.templates.folder)",
   "setting.frontMatter.templates.prefix.markdownDescription": "新しい記事の作成時、ファイル名に付与する接頭辞を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.templates.prefix)",
-  "setting.frontMatter.dashboard.mediaSnippet.deprecationMessage": "🚧: This setting is deprecated and will be removed in the next major version. Please define your media snippet in the `frontMatter.content.snippet` setting.",
-  "setting.frontMatter.taxonomy.dateField.deprecationMessage": "🚧: This setting is deprecated and will be removed in the next major version. Please use the new `isPublishDate` settings instead in your content types date fields.",
-  "setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "🚧: This setting is deprecated and will be removed in the next major version. Please use the new `isModifiedDate` settings instead in your content types date fields.",
-  "setting.frontMatter.global.disabledNotifications.markdownDescription": "🚧: This is an array with the notifications types that can be disabled for Front Matter CMS. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "🚧: Specify the name of the custom field type to use.",
-  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "🚧: Specify if the empty values should be cleared.",
-  "setting.frontMatter.website.host.markdownDescription": "🚧: Specify the host URL of your website. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
-  "command.frontMatter.settings.refresh": "🚧: Refresh Front Matter Settings"
+  "setting.frontMatter.dashboard.mediaSnippet.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。メディア スニペットは 'frontMatter.content.snippet' 設定で定義してください。",
+  "setting.frontMatter.taxonomy.dateField.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。代わりに、コンテンツ タイプの日付フィールドで新しい 'isPublishDate' 設定を使用してください。",
+  "setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。代わりに、コンテンツ タイプの日付フィールドで新しい 'isModifiedDate' 設定を使用してください。",
+  "setting.frontMatter.global.disabledNotifications.markdownDescription": "これは、Front Matter CMS で無効にできる通知タイプの配列です。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "使用するユーザー設定フィールド型の名前を指定します。",
+  "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "空の値をクリアするかどうかを指定します。",
+  "setting.frontMatter.website.host.markdownDescription": "ウェブサイトのホスト URL を指定します。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
+  "command.frontMatter.settings.refresh": "フロントマター設定の更新",
+  "setting.frontMatter.config.dynamicFilePath.markdownDescription": "動的構成ファイルへのパスを指定します (例: [[ワークスペース]]/config.js)。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)",
+  "setting.frontMatter.content.pageFolders.items.properties.disableCreation.description": "フォルダー内の新しいコンテンツの作成を無効にします。",
+  "setting.frontMatter.custom.scripts.items.properties.contentTypes.description": "スクリプトを使用するコンテンツ タイプを定義します。何も定義されていない場合は、すべての型で使用できます。"
 }
\ No newline at end of file
diff --git a/package.nls.json b/package.nls.json
index 4789a27f..d427f13c 100644
--- a/package.nls.json
+++ b/package.nls.json
@@ -74,6 +74,7 @@
   "setting.frontMatter.content.pageFolders.items.properties.previewPath.description": "Defines a custom preview path for the folder.",
   "setting.frontMatter.content.pageFolders.items.properties.filePrefix.description": "Defines a prefix for the file name.",
   "setting.frontMatter.content.pageFolders.items.properties.contentTypes.description": "Defines which content types can be used for the current location. If not defined, all content types will be available.",
+  "setting.frontMatter.content.pageFolders.items.properties.disableCreation.description": "Disable the creation of new content in the folder.",
   "setting.frontMatter.content.placeholders.markdownDescription": "This array of placeholders defines the placeholders that you can use in your content types and templates for automatically populating your content its front matter. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.content.placeholders)",
   "setting.frontMatter.content.placeholders.items.properties.id.description": "ID of the placeholder, in your content type or template, use it as follows: {{placeholder}}",
   "setting.frontMatter.content.placeholders.items.properties.value.description": "The placeholder its value",
@@ -104,6 +105,7 @@
   "setting.frontMatter.custom.scripts.items.properties.hidden.description": "Hide the action from the UI",
   "setting.frontMatter.custom.scripts.items.properties.environments.items.properties.type.description": "The environment type for which the script needs to be used",
   "setting.frontMatter.custom.scripts.items.properties.environments.items.properties.script.description": "Path to the script to execute",
+  "setting.frontMatter.custom.scripts.items.properties.contentTypes.description": "Define the content types for which the script will be used. If none are defined, it will be available to all types.",
   "setting.frontMatter.dashboard.content.pagination.markdownDescription": "Specify if you want to enable/disable pagination for your content. You can define your page number up to 52. Default items per page is `16`. Disabling the pagination can be done by setting it to `false`. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.content.pagination)",
   "setting.frontMatter.dashboard.content.cardTags.markdownDescription": "Specify the name of the metadata field that will be used to show the tags on the content card. When empty or null, it will hide the tags from the card. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.content.cardtags)",
   "setting.frontMatter.dashboard.content.card.fields.state.markdownDescription": "Specify if you want to show the state/draft status on the content card view. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.state)",
@@ -215,7 +217,7 @@
   "setting.frontMatter.taxonomy.customTaxonomy.items.properties.options.description": "Options from which you can pick.",
   "setting.frontMatter.taxonomy.dateField.markdownDescription": "This setting is used to define the publishing date field of your articles. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.datefield)",
   "setting.frontMatter.taxonomy.dateFormat.markdownDescription": "Specify the date format for your articles. Check [date-fns formating](https://date-fns.org/v2.0.1/docs/format) for more information. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.dateformat)",
-  "setting.frontMatter.taxonomy.fieldGroups.markdownDescription": "Define the field groups you want to use for your block fields. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.fieldgroups)",
+  "setting.frontMatter.taxonomy.fieldGroups.markdownDescription": "Define the field groups you want to use for your block fields or collection fields. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.fieldgroups)",
   "setting.frontMatter.taxonomy.fieldGroups.items.properties.id.description": "The name of the field group",
   "setting.frontMatter.taxonomy.fieldGroups.items.properties.labelField.description": "The name of the field to be used as display value",
   "setting.frontMatter.taxonomy.frontMatterType.markdownDescription": "Specify the type of Front Matter to use. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.frontmattertype)",
@@ -242,5 +244,6 @@
   "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "Specify the name of the custom field type to use.",
   "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "Specify if the empty values should be cleared.",
   "setting.frontMatter.website.host.markdownDescription": "Specify the host URL of your website. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
-  "command.frontMatter.settings.refresh": "Refresh Front Matter Settings"
+  "command.frontMatter.settings.refresh": "Refresh Front Matter Settings",
+  "setting.frontMatter.config.dynamicFilePath.markdownDescription": "Specify the path to the dynamic config file (ex: [[workspace]]/config.js). [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)"
 }
\ No newline at end of file
diff --git a/scripts/sync-localization.js b/scripts/sync-localization.js
index c915f8e0..cc81b40d 100644
--- a/scripts/sync-localization.js
+++ b/scripts/sync-localization.js
@@ -1,6 +1,42 @@
 const fs = require('fs');
 const path = require('path');
 const glob = require('glob');
+const { v4: uuidv4 } = require('uuid');
+require('dotenv').config()
+
+const transKey = process.env.TRANSLATION_API_KEY || "";
+const apiUrl = process.env.TRANSLATION_API_URL || "";
+const location = process.env.TRANSLATION_API_LOCATION || "";
+
+const getTranslation = (translation) => {
+  let value = undefined;
+
+  if (translation && translation.translations && translation.translations.length > 0) {
+    value = translation.translations[0].text;
+  }
+
+  return value;
+}
+
+const callTranslationService = async (body, locale) => {
+  const response = await fetch(`${apiUrl}/translate?api-version=3.0&from=en&to=${locale}`, {
+    method: 'POST',
+    headers: {
+      'Ocp-Apim-Subscription-Key': transKey,
+      'Ocp-Apim-Subscription-Region': location,
+      'Content-type': 'application/json',
+      'Accept': 'application/json',
+      'X-ClientTraceId': uuidv4().toString(),
+    },
+    body
+  });
+
+  if (!response.ok) {
+    return undefined;
+  }
+
+  return await response.json();
+}
 
 (async () => {
   // Get all the files from the l10n directory
@@ -11,6 +47,7 @@ const glob = require('glob');
   const enContent = JSON.parse(enFile);
   const enKeys = Object.keys(enContent);
 
+  console.log(`Starting l10n bundles`);
   for (const file of files) {
     if (file.endsWith(`bundle.l10n.json`)) {
       continue;
@@ -20,17 +57,54 @@ const glob = require('glob');
     const fileContent = fs.readFileSync(path.join(__dirname, `../l10n/${file}`), 'utf8');
     let content = {};
 
+    // Get the locale
+    const fileName = path.basename(file);
+    const fileSplit = fileName.split('.');
+    const locale = fileSplit[fileSplit.length - 2];
+    if (!locale) {
+      continue;
+    }
+    console.log(`- Processing: ${locale}`);
+
     try {
       content = JSON.parse(fileContent);
     } catch (e) {
       // Ignore the error
     }
 
+    const keysToTranslate = [];
+
     // Loop through the EN keys
     for (const key of enKeys) {
       // If the key does not exist in the file, add it
-      if (!content[key]) {
-        content[key] = `🚧: ${enContent[key]}`;
+      if (!content[key] || content[key].startsWith(`🚧: `)) {
+        keysToTranslate.push({
+          name: key,
+          value: enContent[key],
+        });
+
+        if (!apiUrl || !transKey || !location) {
+          content[key] = `${enContent[key]}`;
+        }
+      }
+    }
+
+    if (apiUrl && transKey && location) {
+      if (keysToTranslate.length > 0) {
+        console.log(`  - Translating: ${keysToTranslate.length}`);
+        const body = JSON.stringify(keysToTranslate.map(key => ({ text: key.value })));
+        const data = await callTranslationService(body, locale);
+        
+        for (let i = 0; i < keysToTranslate.length; i++) {
+          const keyToTranslate = keysToTranslate[i];
+          const translation = getTranslation(data[i]);
+
+          if (keyToTranslate.name && translation) {
+            content[keyToTranslate.name] = translation;
+          } else {
+            content[keyToTranslate.name] = `${keyToTranslate.value}`;
+          }
+        }
       }
     }
 
@@ -46,21 +120,60 @@ const glob = require('glob');
 
   const pkgFiles = glob.sync(path.join(__dirname, '../package.nls.*.json'));
 
+  console.log(``);
+  console.log(`Starting nls bundles`);
   for (const file of pkgFiles) {
     const fileContent = fs.readFileSync(file, 'utf8');
     let content = {};
 
+    // Get the locale
+    const fileName = path.basename(file);
+    const fileSplit = fileName.split('.');
+    const locale = fileSplit[fileSplit.length - 2];
+    if (!locale) {
+      continue;
+    }
+    console.log(`- Processing: ${locale}`);
+
     try {
       content = JSON.parse(fileContent);
     } catch (e) {
       // Ignore the error
     }
 
+    const keysToTranslate = [];
+
     // Loop through the EN keys
     for (const key of enPkgKeys) {
-      // If the key does not exist in the file, add it
-      if (!content[key]) {
-        content[key] = `🚧: ${enPkgContent[key]}`;
+      const contentValue = content[key];
+      if (!contentValue || contentValue.startsWith(`🚧: `)) {
+        keysToTranslate.push({
+          name: key,
+          value: enPkgContent[key],
+        });
+
+        if (!apiUrl || !transKey || !location) {
+          content[key] = `🚧: ${enPkgContent[key]}`;
+        }
+      }
+    }
+
+    if (apiUrl && transKey && location) {
+      if (keysToTranslate.length > 0) {
+        console.log(`  - Translating: ${keysToTranslate.length}`);
+        const body = JSON.stringify(keysToTranslate.map(key => ({ text: key.value })));
+        const data = await callTranslationService(body, locale);
+        
+        for (let i = 0; i < keysToTranslate.length; i++) {
+          const keyToTranslate = keysToTranslate[i];
+          const translation = getTranslation(data[i]);
+
+          if (keyToTranslate.name && translation) {
+            content[keyToTranslate.name] = translation;
+          } else {
+            content[keyToTranslate.name] = `${keyToTranslate.value}`;
+          }
+        }
       }
     }
 
diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts
index 03b7df40..342b747f 100644
--- a/src/commands/Dashboard.ts
+++ b/src/commands/Dashboard.ts
@@ -6,7 +6,7 @@ import {
   SETTING_EXTENSIBILITY_SCRIPTS
 } from '../constants';
 import { join } from 'path';
-import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace } from 'vscode';
+import { commands, Uri, ViewColumn, Webview, WebviewPanel, window } from 'vscode';
 import { Logger, Settings as SettingsHelper } from '../helpers';
 import { DashboardCommand } from '../dashboardWebView/DashboardCommand';
 import { Extension } from '../helpers/Extension';
@@ -23,7 +23,8 @@ import {
   SnippetListener,
   TaxonomyListener,
   LogListener,
-  LocalizationListener
+  LocalizationListener,
+  SsgListener
 } from '../listeners/dashboard';
 import { MediaListener as PanelMediaListener } from '../listeners/panel';
 import { GitListener, ModeListener } from '../listeners/general';
@@ -134,7 +135,7 @@ export class Dashboard {
       light: Uri.file(join(extensionUri.fsPath, 'assets/icons/frontmatter-short-light.svg'))
     };
 
-    Dashboard.webview.webview.html = Dashboard.getWebviewContent(
+    Dashboard.webview.webview.html = await Dashboard.getWebviewContent(
       Dashboard.webview.webview,
       extensionUri
     );
@@ -180,6 +181,7 @@ export class Dashboard {
       GitListener.process(msg);
       TaxonomyListener.process(msg);
       LogListener.process(msg);
+      SsgListener.process(msg);
     });
   }
 
@@ -202,6 +204,7 @@ export class Dashboard {
     command: DashboardCommand;
     requestId?: string;
     payload?: unknown;
+    error?: unknown;
   }) {
     if (Dashboard.isDisposed) {
       return;
@@ -216,7 +219,7 @@ export class Dashboard {
    * Retrieve the webview HTML contents
    * @param webView
    */
-  private static getWebviewContent(webView: Webview, extensionPath: Uri): string {
+  private static async getWebviewContent(webView: Webview, extensionPath: Uri): Promise<string> {
     const dashboardFile = 'dashboardWebView.js';
     const localPort = `9000`;
     const localServerUrl = `localhost:${localPort}`;
@@ -274,10 +277,9 @@ export class Dashboard {
       }`
     ];
 
+    const globalConfigPath = await SettingsHelper.projectConfigPath();
     const frontMatterUri = webView
-      .asWebviewUri(
-        SettingsHelper.projectConfigPath ? Uri.file(SettingsHelper.projectConfigPath) : Uri.file('')
-      )
+      .asWebviewUri(globalConfigPath ? Uri.file(globalConfigPath) : Uri.file(''))
       .toString();
 
     const webviewUrl = frontMatterUri.replace(`/${SettingsHelper.globalFile}`, '');
diff --git a/src/commands/Folders.ts b/src/commands/Folders.ts
index f125ead1..0a6cfe0a 100644
--- a/src/commands/Folders.ts
+++ b/src/commands/Folders.ts
@@ -95,7 +95,7 @@ export class Folders {
       return;
     }
 
-    const folders = Folders.get();
+    const folders = Folders.get().filter((f) => !f.disableCreation);
     const location = folders.find((f) => f.title === selectedFolder);
     if (location) {
       const folderPath = Folders.getFolderPath(Uri.file(location.path));
@@ -109,9 +109,12 @@ export class Folders {
    * Register the new folder path
    * @param folderInfo
    */
-  public static async register(folderInfo: { title: string; path: Uri } | Uri) {
+  public static async register(
+    folderInfo: { title: string; path: Uri; contentType: string[] } | Uri
+  ) {
     let folderName = folderInfo instanceof Uri ? undefined : folderInfo.title;
     const folder = folderInfo instanceof Uri ? folderInfo : folderInfo.path;
+    const contentType = folderInfo instanceof Uri ? undefined : folderInfo.contentType;
 
     if (folder && folder.fsPath) {
       const wslPath = folder.fsPath.replace(/\//g, '\\');
@@ -137,10 +140,16 @@ export class Folders {
         });
       }
 
-      folders.push({
+      const contentFolder = {
         title: folderName,
         path: folder.fsPath
-      } as ContentFolder);
+      } as ContentFolder;
+
+      if (contentType) {
+        contentFolder.contentTypes = typeof contentType === 'string' ? [contentType] : contentType;
+      }
+
+      folders.push(contentFolder);
 
       folders = uniqBy(folders, (f) => f.path);
       await Folders.update(folders);
@@ -429,9 +438,14 @@ export class Folders {
   public static getAbsFilePath(filePath: string): string {
     const wsFolder = Folders.getWorkspaceFolder();
     const isWindows = process.platform === 'win32';
-    let absPath = filePath.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || ''));
-    absPath = isWindows ? absPath.split('/').join('\\') : absPath;
-    return parseWinPath(absPath);
+
+    if (filePath.includes(WORKSPACE_PLACEHOLDER)) {
+      let absPath = filePath.replace(WORKSPACE_PLACEHOLDER, parseWinPath(wsFolder?.fsPath || ''));
+      absPath = isWindows ? absPath.split('/').join('\\') : absPath;
+      return parseWinPath(absPath);
+    }
+
+    return parseWinPath(join(parseWinPath(wsFolder?.fsPath || ''), filePath));
   }
 
   /**
@@ -583,7 +597,7 @@ export class Folders {
    */
   private static findFolders(pattern: string): Promise<string[]> {
     return new Promise((resolve) => {
-      glob(pattern, { ignore: '**/node_modules/**' }, (err, files) => {
+      glob(pattern, { ignore: '**/node_modules/**', dot: true }, (err, files) => {
         const allFolders = files.map((file) => dirname(file));
         const uniqueFolders = [...new Set(allFolders)];
         resolve(uniqueFolders);
diff --git a/src/commands/Preview.ts b/src/commands/Preview.ts
index 89b3454e..17a512d8 100644
--- a/src/commands/Preview.ts
+++ b/src/commands/Preview.ts
@@ -13,7 +13,7 @@ import {
 } from './../constants';
 import { ArticleHelper } from './../helpers/ArticleHelper';
 import { join, parse } from 'path';
-import { commands, env, Uri, ViewColumn, window, WebviewPanel } from 'vscode';
+import { commands, env, Uri, ViewColumn, window, WebviewPanel, extensions } from 'vscode';
 import { Extension, parseWinPath, processKnownPlaceholders, Settings } from '../helpers';
 import { ContentFolder, ContentType, PreviewSettings } from '../models';
 import { format } from 'date-fns';
@@ -22,7 +22,6 @@ import { Article } from '.';
 import { urlJoin } from 'url-join-ts';
 import { WebviewHelper } from '@estruyf/vscode';
 import { Folders } from './Folders';
-import { DataListener } from '../listeners/panel';
 import { ParsedFrontMatter } from '../parsers';
 import { getLocalizationFile } from '../utils/getLocalizationFile';
 
@@ -48,17 +47,26 @@ export class Preview {
       return;
     }
 
+    const browserLiteCommand = await this.getBrowserLiteCommand();
+
     const editor = window.activeTextEditor;
     const crntFilePath = editor?.document.uri.fsPath;
     this.filePath = crntFilePath;
 
-    if (crntFilePath && this.webviews[crntFilePath]) {
+    if (crntFilePath && this.webviews[crntFilePath] && !browserLiteCommand) {
       this.webviews[crntFilePath].reveal();
       return;
     }
 
     const article = editor ? ArticleHelper.getFrontMatter(editor) : null;
     const slug = await this.getContentSlug(article, editor?.document.uri.fsPath);
+    const localhostUrl = await this.getLocalServerUrl();
+
+    if (browserLiteCommand) {
+      const pageUrl = urlJoin(localhostUrl.toString(), slug || '');
+      commands.executeCommand(browserLiteCommand, pageUrl);
+      return;
+    }
 
     // Create the preview webview
     const webView = window.createWebviewPanel(
@@ -82,29 +90,12 @@ export class Preview {
       light: Uri.file(join(extensionPath, 'assets/icons/frontmatter-short-light.svg'))
     };
 
-    const localhostUrl = await this.getLocalServerUrl();
-
     const cspSource = webView.webview.cspSource;
 
     webView.onDidDispose(() => {
-      this.filePath = undefined;
-      if (crntFilePath) {
-        delete this.webviews[crntFilePath];
-      }
       webView.dispose();
     });
 
-    webView.onDidChangeViewState(async (e) => {
-      if (e.webviewPanel.visible) {
-        this.filePath = crntFilePath;
-
-        if (crntFilePath) {
-          const article = await ArticleHelper.getFrontMatterByPath(crntFilePath);
-          DataListener.pushMetadata(article?.data);
-        }
-      }
-    });
-
     webView.webview.onDidReceiveMessage(async (message) => {
       switch (message.command) {
         case PreviewCommands.toVSCode.open:
@@ -258,10 +249,16 @@ export class Preview {
 
       if (!selectedFolder && article?.data && contentType && !contentType.previewPath) {
         // Try to find the folder by content type
-        const crntFolders = folders.filter((folder) =>
-          folder.contentTypes?.includes((contentType as ContentType).name)
+        let crntFolders = folders.filter(
+          (folder) =>
+            folder.contentTypes?.includes((contentType as ContentType).name) && folder.previewPath
         );
 
+        // Use file path to find the folder
+        if (crntFolders.length > 0) {
+          crntFolders = crntFolders.filter((folder) => filePath?.startsWith(folder.path));
+        }
+
         if (crntFolders && crntFolders.length === 1) {
           selectedFolder = crntFolders[0];
         } else if (crntFolders && crntFolders.length > 1) {
@@ -338,6 +335,22 @@ export class Preview {
     return slug;
   }
 
+  /**
+   * Check if Browser Lite is installed
+   */
+  private static async getBrowserLiteCommand() {
+    const ext = extensions.getExtension(`antfu.browse-lite`);
+    if (ext && ext.packageJSON) {
+      const hasCommand = ext.packageJSON.contributes?.commands?.find(
+        (c: { command: string }) => c.command === 'browse-lite.open'
+      );
+      if (hasCommand) {
+        return 'browse-lite.open';
+      }
+    }
+    return undefined;
+  }
+
   /**
    * Retrieve the localhost url
    * @returns
diff --git a/src/commands/Project.ts b/src/commands/Project.ts
index 7fe1c953..2281ae63 100644
--- a/src/commands/Project.ts
+++ b/src/commands/Project.ts
@@ -43,8 +43,8 @@ categories: []
     subscriptions.push(commands.registerCommand(COMMAND_NAME.switchProject, Project.switchProject));
   }
 
-  public static isInitialized() {
-    const hasProjectFile = Settings.hasProjectFile();
+  public static async isInitialized() {
+    const hasProjectFile = await Settings.hasProjectFile();
     // If it has a project file, initialize the media library
     if (hasProjectFile) {
       MediaLibrary.getInstance();
diff --git a/src/commands/StatusListener.ts b/src/commands/StatusListener.ts
index 0ad6fc7c..b2585957 100644
--- a/src/commands/StatusListener.ts
+++ b/src/commands/StatusListener.ts
@@ -29,7 +29,7 @@ export class StatusListener {
     let document = editor?.document;
 
     if (!document) {
-      const filePath = Preview.filePath;
+      const filePath = Preview.filePath || ArticleHelper.getActiveFile();
       if (filePath) {
         document = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath));
       }
diff --git a/src/constants/FrameworkDetectors.ts b/src/constants/FrameworkDetectors.ts
index 7bc87a3a..dc7e899c 100644
--- a/src/constants/FrameworkDetectors.ts
+++ b/src/constants/FrameworkDetectors.ts
@@ -65,7 +65,7 @@ export const FrameworkDetectors = [
     requiredFiles: ['nuxt.config.js'],
     requiredDependencies: ['nuxt'],
     commands: {
-      start: 'npx nuxt'
+      start: 'npx nuxt dev'
     }
   },
   {
diff --git a/src/constants/LocalStore.ts b/src/constants/LocalStore.ts
index e3ecc86c..04c9443f 100644
--- a/src/constants/LocalStore.ts
+++ b/src/constants/LocalStore.ts
@@ -4,5 +4,6 @@ export const LocalStore = {
   databaseFolder: 'database',
   templatesFolder: 'templates',
   mediaDatabaseFile: 'mediaDb.json',
-  taxonomyDatabaseFile: 'taxonomyDb.json'
+  taxonomyDatabaseFile: 'taxonomyDb.json',
+  pinnedItemsDatabaseFile: 'pinnedItemsDb.json'
 };
diff --git a/src/constants/SsgScripts.ts b/src/constants/SsgScripts.ts
new file mode 100644
index 00000000..7c3e2c71
--- /dev/null
+++ b/src/constants/SsgScripts.ts
@@ -0,0 +1,5 @@
+export const SsgScripts = {
+  folder: '/ssg-scripts',
+  astroContentCollectionScript: 'astro.collections.mjs',
+  astroContentCollectionJSON: 'astro.collections.json'
+};
diff --git a/src/constants/index.ts b/src/constants/index.ts
index e4a8731d..ca2aea05 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -14,6 +14,7 @@ export * from './NotificationType';
 export * from './PreviewCommands';
 export * from './SentryIgnore';
 export * from './Snippet';
+export * from './SsgScripts';
 export * from './StaticFolderPlaceholder';
 export * from './TelemetryEvent';
 export * from './Templates';
diff --git a/src/constants/settings.ts b/src/constants/settings.ts
index fecbae26..02a818b8 100644
--- a/src/constants/settings.ts
+++ b/src/constants/settings.ts
@@ -7,6 +7,7 @@ export const SETTING_EXPERIMENTAL = 'experimental';
 export const SETTING_EXTENSIBILITY_SCRIPTS = 'extensibility.scripts';
 
 export const SETTING_EXTENDS = 'extends';
+export const SETTING_CONFIG_DYNAMIC_FILE_PATH = 'config.dynamicFilePath';
 
 export const SETTING_GLOBAL_NOTIFICATIONS = 'global.notifications';
 export const SETTING_GLOBAL_NOTIFICATIONS_DISABLED = 'global.disabledNotifications';
@@ -45,6 +46,7 @@ export const SETTING_TEMPLATES_ENABLED = 'templates.enabled';
 export const SETTING_TELEMETRY_DISABLE = 'telemetry.disable';
 
 export const SETTING_PANEL_FREEFORM = 'panel.freeform';
+export const SETTING_PANEL_ACTIONS_DISABLED = 'panel.actions.disabled';
 
 export const SETTING_PREVIEW_HOST = 'preview.host';
 export const SETTING_PREVIEW_PATHNAME = 'preview.pathName';
diff --git a/src/dashboardWebView/DashboardMessage.ts b/src/dashboardWebView/DashboardMessage.ts
index 1325bd9e..043e0808 100644
--- a/src/dashboardWebView/DashboardMessage.ts
+++ b/src/dashboardWebView/DashboardMessage.ts
@@ -14,6 +14,8 @@ export enum DashboardMessage {
   addFolder = 'addFolder',
   addAssetsFolder = 'addAssetsFolder',
   triggerTemplate = 'triggerTemplate',
+  ssgGetAstroContentTypes = 'ssgGetAstroContentTypes',
+  ssgSetAstroContentTypes = 'ssgSetAstroContentTypes',
 
   // Content dashboard
   getData = 'getData',
@@ -24,6 +26,9 @@ export enum DashboardMessage {
   searchPages = 'searchPages',
   openFile = 'openFile',
   deleteFile = 'deleteFile',
+  getPinnedItems = 'getPinnedItems',
+  pinItem = 'pinItem',
+  unpinItem = 'unpinItem',
 
   // Media Dashboard
   getMedia = 'getMedia',
@@ -37,6 +42,8 @@ export enum DashboardMessage {
   createMediaFolder = 'createMediaFolder',
   insertFile = 'insertFile',
   createHexoAssetFolder = 'createHexoAssetFolder',
+  getUnmappedMedia = 'getUnmappedMedia',
+  remapMediaMetadata = 'remapMediaMetadata',
 
   // Data dashboard
   getDataEntries = 'getDataEntries',
@@ -63,5 +70,9 @@ export enum DashboardMessage {
   setState = 'setState',
   runCustomScript = 'runCustomScript',
   sendTelemetry = 'sendTelemetry',
-  logError = 'logError'
+  logError = 'logError',
+
+  // Settings
+  getSettings = 'getSettings',
+  setSettings = 'setSettings'
 }
diff --git a/src/dashboardWebView/components/App.tsx b/src/dashboardWebView/components/App.tsx
index 8e82e94a..213c9e61 100644
--- a/src/dashboardWebView/components/App.tsx
+++ b/src/dashboardWebView/components/App.tsx
@@ -21,6 +21,7 @@ import { ErrorView } from './ErrorView';
 import { DashboardMessage } from '../DashboardMessage';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../localization';
+import { SettingsView } from './SettingsView/SettingsView';
 
 export interface IAppProps {
   showWelcome: boolean;
@@ -133,6 +134,8 @@ Stack: ${componentStack}`
             <Route path={routePaths.taxonomy} element={<TaxonomyView pages={pages} />} />
           )}
 
+          <Route path={routePaths.settings} element={<SettingsView />} />
+
           <Route path={`*`} element={<UnknownView />} />
         </Routes>
       </main>
diff --git a/src/dashboardWebView/components/Common/Spinner.tsx b/src/dashboardWebView/components/Common/Spinner.tsx
index 6cf166df..0b87e2a0 100644
--- a/src/dashboardWebView/components/Common/Spinner.tsx
+++ b/src/dashboardWebView/components/Common/Spinner.tsx
@@ -1,23 +1,17 @@
 import * as React from 'react';
-import useThemeColors from '../../hooks/useThemeColors';
 
 export interface ISpinnerProps { }
 
 export const Spinner: React.FunctionComponent<ISpinnerProps> = (
-  props: React.PropsWithChildren<ISpinnerProps>
+  _: React.PropsWithChildren<ISpinnerProps>
 ) => {
-  const { getColors } = useThemeColors();
-
   return (
-    <div
-      className={`fixed top-0 left-0 right-0 bottom-0 w-full h-full flex flex-wrap items-center justify-center z-50 ${getColors(
-        `bg-black bg-opacity-50`,
-        `bg-[var(--vscode-editor-background)] opacity-75`
-      )
-        }`}
-    >
-      <div className={`loader ease-linear rounded-full border-8 border-t-8 h-16 w-16 ${getColors(`border-gray-50 border-t-teal-500`, `border-[var(--vscode-activityBar-inactiveForeground)] border-t-[var(--vscode-activityBarBadge-background)]`)
-        }`} />
+    <div className={`z-50 fixed top-0 left-0 right-0 bottom-0 w-full h-full bg-[var(--vscode-editor-background)] opacity-75`}>
+      <div
+        className={`absolute top-0 w-full h-[2px] `}
+      >
+        <div className={`h-full absolute rounded-sm bg-[var(--vscode-activityBarBadge-background)] animate-[vscode-loader_4s_ease-in-out_infinite]`} />
+      </div>
     </div>
   );
-};
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/Configuration/Astro/AstroContentTypes.tsx b/src/dashboardWebView/components/Configuration/Astro/AstroContentTypes.tsx
new file mode 100644
index 00000000..b23339b9
--- /dev/null
+++ b/src/dashboardWebView/components/Configuration/Astro/AstroContentTypes.tsx
@@ -0,0 +1,69 @@
+import * as React from 'react';
+import * as l10n from '@vscode/l10n';
+import { messageHandler } from '@estruyf/vscode/dist/client';
+import { DashboardMessage } from '../../../DashboardMessage';
+import { AstroCollection } from '../../../../models';
+import { Settings } from '../../../models';
+import { SelectItem } from '../../Steps/SelectItem';
+import { LocalizationKey } from '../../../../localization';
+
+export interface IAstroContentTypesProps {
+  settings: Settings
+  triggerLoading: (isLoading: boolean) => void;
+}
+
+export const AstroContentTypes: React.FunctionComponent<IAstroContentTypesProps> = ({
+  settings,
+  triggerLoading
+}: React.PropsWithChildren<IAstroContentTypesProps>) => {
+  const [collections, setCollections] = React.useState<AstroCollection[]>([]);
+
+  React.useEffect(() => {
+    triggerLoading(true);
+    messageHandler.request<AstroCollection[]>(DashboardMessage.ssgGetAstroContentTypes).then((result) => {
+      triggerLoading(false);
+      setCollections(result);
+    });
+  }, []);
+
+  const generateContentType = (collection: AstroCollection) => {
+    triggerLoading(true);
+    messageHandler.request(DashboardMessage.ssgSetAstroContentTypes, {
+      collection
+    }).then((result) => {
+      triggerLoading(false);
+    });
+  }
+
+  if (!collections || collections.length === 0) {
+    return (
+      <div className='mt-1'>
+        {l10n.t(LocalizationKey.dashboardConfigurationAstroAstroContentTypesEmpty)}
+      </div>
+    );
+  }
+
+  return (
+    <div className='mt-1'>
+      <p>{l10n.t(LocalizationKey.dashboardConfigurationAstroAstroContentTypesDescription)}</p>
+
+      <div className='mt-2'>
+        {
+          (collections || []).map((collection) => {
+            const ct = settings.contentTypes.find((c) => c.name === collection.name);
+
+            return (
+              <SelectItem
+                key={collection.name}
+                title={collection.name}
+                buttonTitle={collection.name}
+                isSelected={ct !== undefined}
+                onClick={() => generateContentType(collection)}
+                disabled={ct !== undefined} />
+            )
+          })
+        }
+      </div>
+    </div>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/Configuration/Common/ContentFolders.tsx b/src/dashboardWebView/components/Configuration/Common/ContentFolders.tsx
new file mode 100644
index 00000000..25ac1063
--- /dev/null
+++ b/src/dashboardWebView/components/Configuration/Common/ContentFolders.tsx
@@ -0,0 +1,50 @@
+import * as React from 'react';
+import * as l10n from '@vscode/l10n';
+import { LocalizationKey } from '../../../../localization';
+import { Settings } from '../../../models';
+import { Folder } from './Folder';
+import { Messenger } from '@estruyf/vscode/dist/client';
+import { DashboardMessage } from '../../../DashboardMessage';
+
+export interface IContentFoldersProps {
+  settings: Settings
+  triggerLoading: (isLoading: boolean) => void;
+}
+
+export const ContentFolders: React.FunctionComponent<IContentFoldersProps> = ({
+  settings
+}: React.PropsWithChildren<IContentFoldersProps>) => {
+
+  const addFolder = (folder: string) => {
+    Messenger.send(DashboardMessage.addFolder, folder);
+  };
+
+  return (
+    <>
+      <p>
+        {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersDescription)}
+      </p>
+
+      {settings?.dashboardState?.welcome?.contentFolders?.length > 0 && (
+        <div className="mt-4">
+          <div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersLabel)}</div>
+          <div className="mt-1 space-y-1">
+            {settings?.dashboardState?.welcome?.contentFolders?.map((folder: string) => (
+              <Folder
+                key={folder}
+                folder={folder}
+                addFolder={addFolder}
+                wsFolder={settings.wsFolder}
+                folders={settings.contentFolders}
+              />
+            ))}
+          </div>
+        </div>
+      )}
+
+      <p className={`mt-4`}>
+        <b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersInformationDescription)}.
+      </p>
+    </>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/Configuration/Common/Folder.tsx b/src/dashboardWebView/components/Configuration/Common/Folder.tsx
new file mode 100644
index 00000000..f3a3d219
--- /dev/null
+++ b/src/dashboardWebView/components/Configuration/Common/Folder.tsx
@@ -0,0 +1,34 @@
+import * as React from 'react';
+import { join } from 'path';
+import * as l10n from '@vscode/l10n';
+import { LocalizationKey } from '../../../../localization';
+import { ContentFolder } from '../../../../models';
+import { SelectItem } from '../../Steps/SelectItem';
+
+export interface IFolderProps {
+  wsFolder: string;
+  folder: string;
+  folders: ContentFolder[];
+  addFolder: (folder: string) => void;
+}
+
+export const Folder: React.FunctionComponent<IFolderProps> = ({
+  wsFolder,
+  folder,
+  folders,
+  addFolder
+}: React.PropsWithChildren<IFolderProps>) => {
+
+  const isAdded = React.useMemo(
+    () => folders.find((f) => f.path.toLowerCase() === join(wsFolder, folder).toLowerCase()),
+    [folder, folders, wsFolder]
+  );
+
+  return (
+    <SelectItem
+      title={folder}
+      buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedButtonAddFolderTitle)}
+      isSelected={!!isAdded}
+      onClick={() => addFolder(folder)} />
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/Contents/ContentActions.tsx b/src/dashboardWebView/components/Contents/ContentActions.tsx
index 0cc59cd0..6e3e81d4 100644
--- a/src/dashboardWebView/components/Contents/ContentActions.tsx
+++ b/src/dashboardWebView/components/Contents/ContentActions.tsx
@@ -1,4 +1,4 @@
-import { Messenger } from '@estruyf/vscode/dist/client';
+import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
 import { Menu } from '@headlessui/react';
 import { EyeIcon, GlobeIcon, TerminalIcon, TrashIcon } from '@heroicons/react/outline';
 import * as React from 'react';
@@ -11,13 +11,16 @@ import { useState } from 'react';
 import useThemeColors from '../../hooks/useThemeColors';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
-import { useRecoilValue } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
 import { SettingsSelector } from '../../state';
 import { GeneralCommands } from '../../../constants';
+import { PinIcon } from '../Icons/PinIcon';
+import { PinnedItemsAtom } from '../../state/atom/PinnedItems';
 
 export interface IContentActionsProps {
   title: string;
   path: string;
+  relPath: string;
   scripts: CustomScript[] | undefined;
   listView?: boolean;
   onOpen: () => void;
@@ -26,10 +29,12 @@ export interface IContentActionsProps {
 export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
   title,
   path,
+  relPath,
   scripts,
   onOpen,
   listView
 }: React.PropsWithChildren<IContentActionsProps>) => {
+  const [pinnedItems, setPinnedItems] = useRecoilState(PinnedItemsAtom);
   const [showDeletionAlert, setShowDeletionAlert] = React.useState(false);
   const { getColors } = useThemeColors();
   const settings = useRecoilValue(SettingsSelector);
@@ -68,6 +73,20 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
     }
   }, [settings?.websiteUrl, path]);
 
+  const pinItem = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
+    e.stopPropagation();
+    messageHandler.request<string[]>(DashboardMessage.pinItem, path).then((result) => {
+      setPinnedItems(result || []);
+    })
+  }, [path]);
+
+  const unpinItem = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
+    e.stopPropagation();
+    messageHandler.request<string[]>(DashboardMessage.unpinItem, path).then((result) => {
+      setPinnedItems(result || []);
+    })
+  }, [path]);
+
   const runCustomScript = React.useCallback(
     (e: React.MouseEvent<HTMLButtonElement>, script: CustomScript) => {
       e.stopPropagation();
@@ -76,6 +95,10 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
     [path]
   );
 
+  const isPinned = React.useMemo(() => {
+    return pinnedItems.includes(relPath);
+  }, [pinnedItems, relPath]);
+
   const customScriptActions = React.useMemo(() => {
     return (scripts || [])
       .filter(
@@ -148,6 +171,15 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
                 widthClass="w-44"
                 marginTopClass={listView ? '' : ''}
               >
+                <MenuItem
+                  title={
+                    <div className="flex items-center">
+                      <PinIcon className={`mr-2 h-5 w-5 flex-shrink-0 ${isPinned ? "" : "-rotate-90"}`} aria-hidden={true} />{' '}
+                      <span>{isPinned ? l10n.t(LocalizationKey.commonUnpin) : l10n.t(LocalizationKey.commonPin)}</span>
+                    </div>
+                  }
+                  onClick={(_, e) => isPinned ? unpinItem(e) : pinItem(e)}
+                />
                 <MenuItem
                   title={
                     <div className="flex items-center">
diff --git a/src/dashboardWebView/components/Contents/Contents.tsx b/src/dashboardWebView/components/Contents/Contents.tsx
index 49b1d6d3..2c69012d 100644
--- a/src/dashboardWebView/components/Contents/Contents.tsx
+++ b/src/dashboardWebView/components/Contents/Contents.tsx
@@ -1,7 +1,7 @@
 import * as React from 'react';
-import { useRecoilValue } from 'recoil';
-import { Page } from '../../models';
-import { SettingsSelector } from '../../state';
+import { useRecoilState, useRecoilValue } from 'recoil';
+import { NavigationType, Page } from '../../models';
+import { DashboardViewAtom, SettingsSelector } from '../../state';
 import { Overview } from './Overview';
 import { Spinner } from '../Common/Spinner';
 import { SponsorMsg } from '../Layout/SponsorMsg';
@@ -23,10 +23,13 @@ export const Contents: React.FunctionComponent<IContentsProps> = ({
 }: React.PropsWithChildren<IContentsProps>) => {
   const settings = useRecoilValue(SettingsSelector);
   const { pageItems } = usePages(pages);
+  const [, setView] = useRecoilState(DashboardViewAtom);
 
   const pageFolders = [...new Set(pageItems.map((page) => page.fmFolder))];
 
   useEffect(() => {
+    setView(NavigationType.Contents);
+
     Messenger.send(DashboardMessage.sendTelemetry, {
       event: TelemetryEvent.webviewContentsView
     });
diff --git a/src/dashboardWebView/components/Contents/Item.tsx b/src/dashboardWebView/components/Contents/Item.tsx
index 599e9a18..84240b60 100644
--- a/src/dashboardWebView/components/Contents/Item.tsx
+++ b/src/dashboardWebView/components/Contents/Item.tsx
@@ -8,82 +8,39 @@ import { Messenger } from '@estruyf/vscode/dist/client';
 import { DashboardViewType } from '../../models';
 import { ContentActions } from './ContentActions';
 import { useMemo } from 'react';
-import useThemeColors from '../../hooks/useThemeColors';
 import { Status } from './Status';
 import * as React from 'react';
 import useExtensibility from '../../hooks/useExtensibility';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { useNavigate } from 'react-router-dom';
+import { routePaths } from '../..';
+import useCard from '../../hooks/useCard';
 
 export interface IItemProps extends Page { }
 
 const PREVIEW_IMAGE_FIELD = 'fmPreviewImage';
 
 export const Item: React.FunctionComponent<IItemProps> = ({
-  fmFilePath,
-  fmDateFormat,
-  date,
-  title,
-  description,
-  type,
   ...pageData
 }: React.PropsWithChildren<IItemProps>) => {
   const view = useRecoilValue(ViewSelector);
   const settings = useRecoilValue(SettingsSelector);
   const draftField = useMemo(() => settings?.draftField, [settings]);
   const cardFields = useMemo(() => settings?.dashboardState?.contents?.cardFields, [settings?.dashboardState?.contents?.cardFields]);
+  const { escapedTitle, escapedDescription } = useCard(pageData, settings?.dashboardState?.contents?.cardFields);
+  const navigate = useNavigate();
   const { titleHtml, descriptionHtml, dateHtml, statusHtml, tagsHtml, imageHtml, footerHtml } = useExtensibility({
-    fmFilePath,
-    date,
-    title,
-    description,
-    type,
+    fmFilePath: pageData.fmFilePath,
+    date: pageData.date,
+    title: pageData.title,
+    description: pageData.description,
+    type: pageData.type,
     pageData
   });
-  const { getColors } = useThemeColors();
-
-  const escapedTitle = useMemo(() => {
-    let value = title;
-
-    if (cardFields?.title) {
-      if (cardFields.title === "description") {
-        value = description;
-      } else if (cardFields?.title !== "title") {
-        value = pageData[cardFields?.title] || title;
-      }
-    } else if (cardFields?.title === null) {
-      return null;
-    }
-
-    if (value && typeof value !== 'string') {
-      return l10n.t(LocalizationKey.dashboardContentsItemInvalidTitle);
-    }
-
-    return value;
-  }, [title, description, cardFields?.title, pageData]);
-
-  const escapedDescription = useMemo(() => {
-    let value = description;
-
-    if (cardFields?.description) {
-      if (cardFields.description === "title") {
-        value = title;
-      } else if (cardFields?.description !== "description") {
-        value = pageData[cardFields?.description] || description;
-      }
-    } else if (cardFields?.description === null) {
-      return null;
-    }
-
-    if (value && typeof value !== 'string') {
-      return l10n.t(LocalizationKey.dashboardContentsItemInvalidDescription);
-    }
-
-    return value;
-  }, [description, title, cardFields?.description, pageData]);
 
   const openFile = () => {
-    Messenger.send(DashboardMessage.openFile, fmFilePath);
+    Messenger.send(DashboardMessage.openFile, pageData.fmFilePath);
   };
 
   const tags: string[] | undefined = useMemo(() => {
@@ -105,7 +62,8 @@ export const Item: React.FunctionComponent<IItemProps> = ({
     if (typeof tagsValue === 'string') {
       return [tagsValue];
     } else if (Array.isArray(tagsValue)) {
-      return tagsValue;
+      const items = tagsValue.map(t => typeof t === 'string' ? t : undefined);
+      return items.filter(t => t !== undefined) as string[];
     }
 
     return [];
@@ -119,18 +77,11 @@ export const Item: React.FunctionComponent<IItemProps> = ({
     return (
       <li className="relative">
         <div
-          className={`group flex flex-col items-start content-start h-full w-full text-left shadow-md dark:shadow-none hover:shadow-xl border rounded ${getColors(
-            'bg-gray-50 dark:bg-vulcan-200 text-vulcan-500 dark:text-whisper-500 dark:hover:bg-vulcan-100 border-gray-200 dark:border-vulcan-50',
-            'bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-sideBarTitle-foreground)] border-[var(--frontmatter-border)]'
-          )
-            }`}
+          className={`group flex flex-col items-start content-start h-full w-full text-left shadow-md dark:shadow-none hover:shadow-xl border rounded bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-sideBarTitle-foreground)] border-[var(--frontmatter-border)]`}
         >
           <button
             onClick={openFile}
-            className={`relative h-36 w-full overflow-hidden border-b cursor-pointer ${getColors(
-              'border-gray-100 dark:border-vulcan-100 dark:group-hover:border-vulcan-200',
-              'border-[var(--frontmatter-border)]'
-            )
+            className={`relative h-36 w-full overflow-hidden border-b cursor-pointer border-[var(--frontmatter-border)]
               }`}
           >
             {
@@ -145,17 +96,9 @@ export const Item: React.FunctionComponent<IItemProps> = ({
                   />
                 ) : (
                   <div
-                    className={`flex items-center justify-center ${getColors(
-                      'bg-whisper-500 dark:bg-vulcan-200 dark:group-hover:bg-vulcan-100',
-                      'bg-[var(--vscode-sideBar-background)] group-hover:bg-[var(--vscode-list-hoverBackground)]'
-                    )
-                      }`}
+                    className={`h-full flex items-center justify-center bg-[var(--vscode-sideBar-background)] group-hover:bg-[var(--vscode-list-hoverBackground)]`}
                   >
-                    <MarkdownIcon className={`h-32 ${getColors(
-                      'text-vulcan-100 dark:text-whisper-100',
-                      'text-[var(--vscode-sideBarTitle-foreground)] opacity-80'
-                    )
-                      }`} />
+                    <MarkdownIcon className={`h-32 text-[var(--vscode-sideBarTitle-foreground)] opacity-80`} />
                   </div>
                 )
             }
@@ -175,14 +118,15 @@ export const Item: React.FunctionComponent<IItemProps> = ({
                 dateHtml ? (
                   <div className='mr-4' dangerouslySetInnerHTML={{ __html: dateHtml }} />
                 ) : (
-                  cardFields?.date && <DateField className={`mr-4`} value={date} format={fmDateFormat} />
+                  cardFields?.date && <DateField className={`mr-4`} value={pageData.date} format={pageData.fmDateFormat} />
                 )
               }
             </div>
 
             <ContentActions
-              title={title}
-              path={fmFilePath}
+              title={pageData.title}
+              path={pageData.fmFilePath}
+              relPath={pageData.fmRelFileWsPath}
               scripts={settings?.scripts}
               onOpen={openFile}
             />
@@ -204,7 +148,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
                 descriptionHtml ? (
                   <div dangerouslySetInnerHTML={{ __html: descriptionHtml }} />
                 ) : (
-                  <p className={`text-xs ${getColors('text-vulcan-200 dark:text-whisper-800', 'text-[vara(--vscode-titleBar-activeForeground)]')}`}>{escapedDescription}</p>
+                  <p className={`text-xs text-[vara(--vscode-titleBar-activeForeground)]`}>{escapedDescription}</p>
                 )
               }
             </button>
@@ -217,16 +161,19 @@ export const Item: React.FunctionComponent<IItemProps> = ({
                   <div className="mt-2">
                     {tags.map(
                       (tag, index) => tag && (
-                        <span
+                        <button
                           key={index}
-                          className={`inline-block mr-1 mt-1 text-xs ${getColors(
-                            `text-[#5D561D] dark:text-[#F0ECD0]`,
-                            `text-[var(--vscode-textPreformat-foreground)]`
-                          )
-                            }`}
+                          className={`inline-block mr-1 mt-1 text-xs text-[var(--vscode-textPreformat-foreground)] hover:brightness-75 hover:underline hover:underline-offset-1`}
+                          title={l10n.t(LocalizationKey.commonFilterValue, tag)}
+                          onClick={() => {
+                            const tagField = settings?.dashboardState.contents.tags;
+                            if (tagField) {
+                              navigate(`${routePaths.contents}?taxonomy=${tagField}&value=${tag}`);
+                            }
+                          }}
                         >
                           #{tag}
-                        </span>
+                        </button>
                       )
                     )}
                   </div>
@@ -247,11 +194,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
     return (
       <li className="relative">
         <div
-          className={`px-5 cursor-pointer w-full text-left grid grid-cols-12 gap-x-4 sm:gap-x-6 xl:gap-x-8 py-2 border-b hover:bg-opacity-70 ${getColors(
-            `border-gray-300 hover:bg-gray-200 dark:border-vulcan-50 dark:hover:bg-vulcan-50`,
-            `border-[var(--frontmatter-border)] hover:bg-[var(--vscode-sideBar-background)]`
-          )
-            }`}
+          className={`px-5 cursor-pointer w-full text-left grid grid-cols-12 gap-x-4 sm:gap-x-6 xl:gap-x-8 py-2 border-b hover:bg-opacity-70 border-[var(--frontmatter-border)] hover:bg-[var(--vscode-sideBar-background)]`}
         >
           <div className="col-span-8 font-bold truncate flex items-center space-x-4">
             <button title={`Open: ${escapedTitle}`} onClick={openFile}>
@@ -260,14 +203,15 @@ export const Item: React.FunctionComponent<IItemProps> = ({
 
             <ContentActions
               title={escapedTitle || ""}
-              path={fmFilePath}
+              path={pageData.fmFilePath}
+              relPath={pageData.fmRelFileWsPath}
               scripts={settings?.scripts}
               onOpen={openFile}
               listView
             />
           </div>
           <div className="col-span-2">
-            <DateField value={date} />
+            <DateField value={pageData.date} />
           </div>
           <div className="col-span-2">
             {draftField && draftField.name && <Status draft={pageData[draftField.name]} />}
diff --git a/src/dashboardWebView/components/Contents/Overview.tsx b/src/dashboardWebView/components/Contents/Overview.tsx
index 330f1bb4..c5e7b9bd 100644
--- a/src/dashboardWebView/components/Contents/Overview.tsx
+++ b/src/dashboardWebView/components/Contents/Overview.tsx
@@ -2,19 +2,25 @@ import { Disclosure } from '@headlessui/react';
 import { ChevronRightIcon } from '@heroicons/react/solid';
 import * as React from 'react';
 import { useCallback, useMemo } from 'react';
-import { useRecoilValue } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
 import { groupBy } from '../../../helpers/GroupBy';
 import { FrontMatterIcon } from '../../../panelWebView/components/Icons/FrontMatterIcon';
 import { GroupOption } from '../../constants/GroupOption';
 import { Page } from '../../models/Page';
 import { Settings } from '../../models/Settings';
-import { GroupingSelector, PageAtom } from '../../state';
+import { GroupingSelector, PageAtom, ViewSelector } from '../../state';
 import { Item } from './Item';
 import { List } from './List';
 import usePagination from '../../hooks/usePagination';
 import useThemeColors from '../../hooks/useThemeColors';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { PinnedItemsAtom } from '../../state/atom/PinnedItems';
+import { messageHandler } from '@estruyf/vscode/dist/client';
+import { DashboardMessage } from '../../DashboardMessage';
+import { PinIcon } from '../Icons/PinIcon';
+import { PinnedItem } from './PinnedItem';
+import { DashboardViewType } from '../../models';
 
 export interface IOverviewProps {
   pages: Page[];
@@ -25,10 +31,13 @@ export const Overview: React.FunctionComponent<IOverviewProps> = ({
   pages,
   settings
 }: React.PropsWithChildren<IOverviewProps>) => {
+  const [isReady, setIsReady] = React.useState<boolean>(false);
+  const [pinnedItems, setPinnedItems] = useRecoilState(PinnedItemsAtom);
   const grouping = useRecoilValue(GroupingSelector);
   const page = useRecoilValue(PageAtom);
   const { pageSetNr } = usePagination(settings?.dashboardState.contents.pagination);
   const { getColors } = useThemeColors();
+  const view = useRecoilValue(ViewSelector);
 
   const pagedPages = useMemo(() => {
     if (pageSetNr) {
@@ -36,7 +45,15 @@ export const Overview: React.FunctionComponent<IOverviewProps> = ({
     }
 
     return pages;
-  }, [pages, page, pageSetNr]);
+  }, [pages, page, pageSetNr, pinnedItems, grouping]);
+
+  const pinnedPages = useMemo(() => {
+    if (grouping === GroupOption.none) {
+      return pages.filter((page) => pinnedItems.includes(page.fmRelFileWsPath));
+    }
+
+    return [];
+  }, [pages, pinnedItems, grouping]);
 
   const groupName = useCallback(
     (groupId, groupedPages) => {
@@ -49,6 +66,20 @@ export const Overview: React.FunctionComponent<IOverviewProps> = ({
     [grouping]
   );
 
+  React.useEffect(() => {
+    messageHandler.request<string[]>(DashboardMessage.getPinnedItems).then((items) => {
+      setIsReady(true);
+      setPinnedItems(items || []);
+    }).catch(() => {
+      setIsReady(true);
+      setPinnedItems([]);
+    });
+  }, []);
+
+  if (!isReady) {
+    return null;
+  }
+
   if (!pages || !pages.length) {
     return (
       <div className={`flex items-center justify-center h-full`}>
@@ -108,10 +139,34 @@ export const Overview: React.FunctionComponent<IOverviewProps> = ({
   }
 
   return (
-    <List>
-      {pagedPages.map((page, idx) => (
-        <Item key={`${page.slug}-${idx}`} {...page} />
-      ))}
-    </List>
+    <div className='divide-y divide-[var(--frontmatter-border)]'>
+      {
+        pinnedPages.length > 0 && (
+          <div className='mb-8'>
+            <h1 className='text-xl flex space-x-2 items-center mb-4'>
+              <PinIcon className={`-rotate-45`} />
+              <span>{l10n.t(LocalizationKey.dashboardContentsOverviewPinned)}</span>
+            </h1>
+            <List>
+              {pinnedPages.map((page, idx) => (
+                view === DashboardViewType.List ? (
+                  <Item key={`${page.slug}-${idx}`} {...page} />
+                ) : (
+                  <PinnedItem key={`${page.slug}-${idx}`} {...page} />
+                )
+              ))}
+            </List>
+          </div>
+        )
+      }
+
+      <div className={pinnedItems.length > 0 ? "pt-8" : ""}>
+        <List>
+          {pagedPages.map((page, idx) => (
+            <Item key={`${page.slug}-${idx}`} {...page} />
+          ))}
+        </List>
+      </div>
+    </div>
   );
 };
diff --git a/src/dashboardWebView/components/Contents/PinnedItem.tsx b/src/dashboardWebView/components/Contents/PinnedItem.tsx
new file mode 100644
index 00000000..62a5ac42
--- /dev/null
+++ b/src/dashboardWebView/components/Contents/PinnedItem.tsx
@@ -0,0 +1,57 @@
+import * as React from 'react';
+import { Page } from '../../models';
+import { MarkdownIcon } from '../../../panelWebView/components/Icons/MarkdownIcon';
+import { ContentActions } from './ContentActions';
+import { DashboardMessage } from '../../DashboardMessage';
+import { messageHandler } from '@estruyf/vscode/dist/client';
+import useCard from '../../hooks/useCard';
+import { SettingsSelector } from '../../state';
+import { useRecoilValue } from 'recoil';
+
+export interface IPinnedItemProps extends Page { }
+
+export const PinnedItem: React.FunctionComponent<IPinnedItemProps> = ({
+  ...pageData
+}: React.PropsWithChildren<IPinnedItemProps>) => {
+  const settings = useRecoilValue(SettingsSelector);
+  const { escapedTitle } = useCard(pageData, settings?.dashboardState?.contents?.cardFields);
+
+  const openFile = React.useCallback(() => {
+    messageHandler.send(DashboardMessage.openFile, pageData.fmFilePath);
+  }, [pageData.fmFilePath]);
+
+  return (
+    <li className='group flex w-full border border-[var(--frontmatter-border)] rounded bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-sideBarTitle-foreground)]'>
+      <button onClick={openFile} className='relative h-full w-1/3'>
+        {
+          pageData["fmPreviewImage"] ? (
+            <img
+              src={`${pageData["fmPreviewImage"]}`}
+              alt={pageData.title || ""}
+              className="absolute inset-0 h-full w-full object-left-top object-cover group-hover:brightness-75"
+              loading="lazy"
+            />
+          ) : (
+            <div
+              className={`h-full flex items-center justify-center bg-[var(--vscode-sideBar-background)] group-hover:bg-[var(--vscode-list-hoverBackground)] border-r border-[var(--frontmatter-border)]`}
+            >
+              <MarkdownIcon className={`h-8 text-[var(--vscode-sideBarTitle-foreground)] opacity-80`} />
+            </div>
+          )
+        }
+      </button>
+
+      <button onClick={openFile} className='relative w-2/3 p-4 pr-6 text-left flex items-start'>
+        <p className='font-bold'>{escapedTitle}</p>
+
+        <ContentActions
+          title={pageData.title}
+          path={pageData.fmFilePath}
+          relPath={pageData.fmRelFileWsPath}
+          scripts={settings?.scripts}
+          onOpen={openFile}
+        />
+      </button>
+    </li>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/Contents/Status.tsx b/src/dashboardWebView/components/Contents/Status.tsx
index 8214921a..659c8c31 100644
--- a/src/dashboardWebView/components/Contents/Status.tsx
+++ b/src/dashboardWebView/components/Contents/Status.tsx
@@ -1,8 +1,7 @@
 import * as React from 'react';
 import { useMemo } from 'react';
 import { useRecoilValue } from 'recoil';
-import useThemeColors from '../../hooks/useThemeColors';
-import { SettingsAtom } from '../../state';
+import { SettingsAtom, TabInfoAtom } from '../../state';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
 
@@ -13,8 +12,8 @@ export interface IStatusProps {
 export const Status: React.FunctionComponent<IStatusProps> = ({
   draft
 }: React.PropsWithChildren<IStatusProps>) => {
-  const { getColors } = useThemeColors();
   const settings = useRecoilValue(SettingsAtom);
+  const tabInfo = useRecoilValue(TabInfoAtom);
 
   const draftField = useMemo(() => settings?.draftField, [settings]);
 
@@ -32,7 +31,7 @@ export const Status: React.FunctionComponent<IStatusProps> = ({
     if (draftValue) {
       return (
         <span
-          className={`inline-block px-2 py-1 leading-none rounded-sm font-semibold uppercase tracking-wide text-xs ${getColors(`text-whisper-200 dark:text-vulcan-500 bg-teal-500`, `text-[var(--vscode-badge-foreground)] bg-[var(--vscode-badge-background)]`)}`}
+          className={`inline-block px-2 py-1 leading-none rounded-sm font-semibold uppercase tracking-wide text-xs text-[var(--vscode-badge-foreground)] bg-[var(--vscode-badge-background)]`}
         >
           {draftValue}
         </span>
@@ -42,17 +41,24 @@ export const Status: React.FunctionComponent<IStatusProps> = ({
     }
   }
 
+  if (tabInfo && Object.keys(tabInfo).length <= 1) {
+    return null;
+  }
+
   return (
     <span
       className={`draft__status
         inline-block px-2 py-1 leading-none rounded-sm font-semibold uppercase tracking-wide text-xs 
-        ${getColors(`text-whisper-200 dark:text-vulcan-500`, ``)} 
         ${draftValue ?
-          getColors(`bg-red-500`, 'bg-[var(--vscode-statusBarItem-errorBackground)] text-[var(--vscode-statusBarItem-errorForeground)]') :
-          getColors(`bg-teal-500`, 'bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)]')
+          'bg-[var(--vscode-statusBarItem-errorBackground)] text-[var(--vscode-statusBarItem-errorForeground)]' :
+          'bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)]'
         }`}
     >
-      {draftValue ? l10n.t(LocalizationKey.dashboardContentsStatusDraft) : l10n.t(LocalizationKey.dashboardContentsStatusPublished)}
+      {
+        draftValue ?
+          l10n.t(LocalizationKey.dashboardContentsStatusDraft) :
+          l10n.t(LocalizationKey.dashboardContentsStatusPublished)
+      }
     </span>
   );
 };
diff --git a/src/dashboardWebView/components/DataView/DataView.tsx b/src/dashboardWebView/components/DataView/DataView.tsx
index a1bf7369..fde6a527 100644
--- a/src/dashboardWebView/components/DataView/DataView.tsx
+++ b/src/dashboardWebView/components/DataView/DataView.tsx
@@ -1,7 +1,7 @@
 import * as React from 'react';
 import { Header } from '../Header';
-import { useRecoilValue } from 'recoil';
-import { SettingsSelector } from '../../state';
+import { useRecoilState, useRecoilValue } from 'recoil';
+import { DashboardViewAtom, SettingsSelector } from '../../state';
 import { DataForm } from './DataForm';
 import { useCallback, useEffect, useMemo, useState } from 'react';
 import { DataFile } from '../../../models/DataFile';
@@ -24,6 +24,7 @@ import { NavigationItem } from '../Layout';
 import useThemeColors from '../../hooks/useThemeColors';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { NavigationType } from '../../models';
 
 export interface IDataViewProps { }
 
@@ -35,6 +36,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
   const [dataEntries, setDataEntries] = useState<any | any[] | null>(null);
   const settings = useRecoilValue(SettingsSelector);
   const { getColors } = useThemeColors();
+  const [, setView] = useRecoilState(DashboardViewAtom);
 
   const setSchema = (dataFile: DataFile) => {
     setSelectedData(dataFile);
@@ -135,6 +137,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
   }, [selectedData, , dataEntries, selectedIndex]);
 
   useEffect(() => {
+    setView(NavigationType.Data);
     Messenger.listen(messageListener);
 
     Messenger.send(DashboardMessage.sendTelemetry, {
diff --git a/src/dashboardWebView/components/Header/Grouping.tsx b/src/dashboardWebView/components/Header/Grouping.tsx
index 2a7e867a..61c35d0c 100644
--- a/src/dashboardWebView/components/Header/Grouping.tsx
+++ b/src/dashboardWebView/components/Header/Grouping.tsx
@@ -2,7 +2,7 @@ import { Menu } from '@headlessui/react';
 import * as React from 'react';
 import { useRecoilState, useRecoilValue } from 'recoil';
 import { GroupOption } from '../../constants/GroupOption';
-import { AllPagesAtom, GroupingAtom, PageAtom } from '../../state';
+import { AllPagesAtom, GroupingAtom } from '../../state';
 import { MenuButton, MenuItem, MenuItems } from '../Menu';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
diff --git a/src/dashboardWebView/components/Header/Header.tsx b/src/dashboardWebView/components/Header/Header.tsx
index d8790a5e..7dbe8469 100644
--- a/src/dashboardWebView/components/Header/Header.tsx
+++ b/src/dashboardWebView/components/Header/Header.tsx
@@ -26,11 +26,11 @@ import { GroupOption } from '../../constants/GroupOption';
 import usePagination from '../../hooks/usePagination';
 import { PaginationStatus } from './PaginationStatus';
 import useThemeColors from '../../hooks/useThemeColors';
-import { Startup } from './Startup';
 import { Navigation } from './Navigation';
 import { ProjectSwitcher } from './ProjectSwitcher';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { SettingsLink } from '../SettingsView/SettingsLink';
 
 export interface IHeaderProps {
   header?: React.ReactNode;
@@ -156,7 +156,11 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({
         }`}>
         <Tabs onNavigate={updateView} />
 
-        <ProjectSwitcher />
+        <div className='flex'>
+          <ProjectSwitcher />
+
+          <SettingsLink onNavigate={updateView} />
+        </div>
       </div>
 
       {location.pathname === routePaths.contents && (
@@ -165,8 +169,6 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({
             <Searchbox />
 
             <div className={`flex items-center justify-end space-x-4 flex-1`}>
-              <Startup settings={settings} />
-
               <SyncButton />
 
               <ChoiceButton
diff --git a/src/dashboardWebView/components/Header/Navigation.tsx b/src/dashboardWebView/components/Header/Navigation.tsx
index 7d7360d6..2452b122 100644
--- a/src/dashboardWebView/components/Header/Navigation.tsx
+++ b/src/dashboardWebView/components/Header/Navigation.tsx
@@ -1,7 +1,7 @@
 import * as React from 'react';
 import { useRecoilState, useRecoilValue } from 'recoil';
 import { Tab } from '../../constants/Tab';
-import { AllPagesAtom, SettingsAtom, TabAtom, TabInfoAtom } from '../../state';
+import { SettingsAtom, TabAtom, TabInfoAtom } from '../../state';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
 
@@ -40,24 +40,22 @@ const NavigationItem: React.FunctionComponent<INavigationItemProps> = ({
 export const Navigation: React.FunctionComponent<INavigationProps> = ({
 
 }: React.PropsWithChildren<INavigationProps>) => {
-  const pages = useRecoilValue(AllPagesAtom);
   const [crntTab, setCrntTab] = useRecoilState(TabAtom);
   const tabInfo = useRecoilValue(TabInfoAtom);
   const settings = useRecoilValue(SettingsAtom);
 
-  const tabs = [
-    { name: l10n.t(LocalizationKey.dashboardHeaderNavigationAllArticles), id: Tab.All },
-    { name: l10n.t(LocalizationKey.dashboardHeaderNavigationPublished), id: Tab.Published },
-    { name: l10n.t(LocalizationKey.dashboardHeaderNavigationDraft), id: Tab.Draft }
-  ];
+  const tabs = React.useMemo(() => {
+    const crntTabs = [
+      { name: l10n.t(LocalizationKey.dashboardHeaderNavigationAllArticles), id: Tab.All }
+    ];
 
-  const usesDraft = React.useMemo(() => {
-    return pages.some((x) => x.fmDraft);
-  }, [pages]);
+    if (settings?.draftField?.type === 'boolean' && tabInfo && Object.keys(tabInfo).length > 1) {
+      crntTabs.push({ name: l10n.t(LocalizationKey.dashboardHeaderNavigationPublished), id: Tab.Published });
+      crntTabs.push({ name: l10n.t(LocalizationKey.dashboardHeaderNavigationDraft), id: Tab.Draft });
+    }
 
-  if (!usesDraft) {
-    return null;
-  }
+    return crntTabs;
+  }, [settings?.draftField?.type, tabInfo]);
 
   return (
     <nav className="flex-1 -mb-px flex space-x-6 xl:space-x-8" aria-label="Tabs">
diff --git a/src/dashboardWebView/components/Header/Startup.tsx b/src/dashboardWebView/components/Header/Startup.tsx
index 1e7dcee4..214fc228 100644
--- a/src/dashboardWebView/components/Header/Startup.tsx
+++ b/src/dashboardWebView/components/Header/Startup.tsx
@@ -1,11 +1,12 @@
 import * as React from 'react';
 import { Messenger } from '@estruyf/vscode/dist/client';
 import { Settings } from '../../models';
-import useThemeColors from '../../hooks/useThemeColors';
 import { DashboardMessage } from '../../DashboardMessage';
 import { SETTING_DASHBOARD_OPENONSTART } from '../../../constants';
 import * as l10n from "@vscode/l10n"
 import { LocalizationKey } from '../../../localization';
+import { VSCodeCheckbox } from '@vscode/webview-ui-toolkit/react';
+
 
 export interface IStartupProps {
   settings: Settings | null;
@@ -15,13 +16,12 @@ export const Startup: React.FunctionComponent<IStartupProps> = ({
   settings
 }: React.PropsWithChildren<IStartupProps>) => {
   const [isChecked, setIsChecked] = React.useState(false);
-  const { getColors } = useThemeColors();
 
-  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    setIsChecked(e.target.checked);
+  const onChange = (value: boolean) => {
+    setIsChecked(value);
     Messenger.send(DashboardMessage.updateSetting, {
       name: SETTING_DASHBOARD_OPENONSTART,
-      value: e.target.checked
+      value: value
     });
   };
 
@@ -30,35 +30,10 @@ export const Startup: React.FunctionComponent<IStartupProps> = ({
   }, [settings?.openOnStart]);
 
   return (
-    <div className={`relative flex items-start ml-4`}>
-      <div className="flex items-center h-5">
-        <input
-          id="startup"
-          aria-describedby="startup-description"
-          name="startup"
-          type="checkbox"
-          checked={isChecked}
-          onChange={onChange}
-          className={`h-4 w-4 focus:outline-none rounded ${getColors(
-            `focus:ring-teal-500 text-teal-600 border-gray-300 dark:border-vulcan-50`,
-            `focus:ring-[var(--frontmatter-button-background)] text-[var(--frontmatter-button-background)] border-[var(--vscode-editorWidget-border)]`
-          )
-            }`}
-        />
-      </div>
-      <div className="ml-2 text-sm">
-        <label
-          id="startup-description"
-          htmlFor="startup"
-          className={`font-medium ${getColors(
-            `text-vulcan-50 dark:text-whisper-900`,
-            `text-[var(--vscode-editor-foreground)]`
-          )
-            }`}
-        >
-          {l10n.t(LocalizationKey.dashboardHeaderStartupLabel)}
-        </label>
-      </div>
-    </div>
+    <VSCodeCheckbox
+      onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.checked)}
+      checked={isChecked}>
+      {l10n.t(LocalizationKey.dashboardHeaderStartupLabel)}
+    </VSCodeCheckbox>
   );
 };
diff --git a/src/dashboardWebView/components/Header/Tab.tsx b/src/dashboardWebView/components/Header/Tab.tsx
index 5d175e06..214115e5 100644
--- a/src/dashboardWebView/components/Header/Tab.tsx
+++ b/src/dashboardWebView/components/Header/Tab.tsx
@@ -1,6 +1,5 @@
 import * as React from 'react';
 import { useLocation } from 'react-router-dom';
-import useThemeColors from '../../hooks/useThemeColors';
 import { NavigationType } from '../../models';
 
 export interface ITabProps {
@@ -14,7 +13,6 @@ export const Tab: React.FunctionComponent<ITabProps> = ({
   children
 }: React.PropsWithChildren<ITabProps>) => {
   const location = useLocation();
-  const { getColors } = useThemeColors();
 
   return (
     <button
diff --git a/src/dashboardWebView/components/Icons/PinIcon.tsx b/src/dashboardWebView/components/Icons/PinIcon.tsx
new file mode 100644
index 00000000..ae20db7d
--- /dev/null
+++ b/src/dashboardWebView/components/Icons/PinIcon.tsx
@@ -0,0 +1,13 @@
+import * as React from 'react';
+
+export interface IPinIconProps {
+  className?: string;
+}
+
+export const PinIcon: React.FunctionComponent<IPinIconProps> = ({
+  className
+}: React.PropsWithChildren<IPinIconProps>) => {
+  return (
+    <svg className={className || ""} stroke="currentColor" fill="currentColor" strokeWidth=".5" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M14 5v7h-.278c-.406 0-.778-.086-1.117-.258A2.528 2.528 0 0 1 11.73 11H8.87a3.463 3.463 0 0 1-.546.828 3.685 3.685 0 0 1-.735.633c-.27.177-.565.31-.882.398a3.875 3.875 0 0 1-.985.141h-.5V9H2l-1-.5L2 8h3.222V4h.5c.339 0 .664.047.977.14.312.094.607.227.883.4A3.404 3.404 0 0 1 8.87 6h2.859a2.56 2.56 0 0 1 .875-.734c.338-.172.71-.26 1.117-.266H14zm-.778 1.086a1.222 1.222 0 0 0-.32.156 1.491 1.491 0 0 0-.43.461L12.285 7H8.183l-.117-.336a2.457 2.457 0 0 0-.711-1.047C7.027 5.331 6.427 5.09 6 5v7c.427-.088 1.027-.33 1.355-.617.328-.287.565-.636.71-1.047L8.184 10h4.102l.18.297c.057.094.122.177.195.25.073.073.153.143.242.21.088.069.195.12.32.157V6.086z"></path></svg>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/Media/DetailsSlideOver.tsx b/src/dashboardWebView/components/Media/DetailsSlideOver.tsx
index 0f50d1f2..686c5aa3 100644
--- a/src/dashboardWebView/components/Media/DetailsSlideOver.tsx
+++ b/src/dashboardWebView/components/Media/DetailsSlideOver.tsx
@@ -5,12 +5,11 @@ import { basename } from 'path';
 import * as React from 'react';
 import { Fragment, useCallback, useMemo } from 'react';
 import { DateHelper } from '../../../helpers/DateHelper';
-import { MediaInfo } from '../../../models';
-import { Messenger } from '@estruyf/vscode/dist/client';
+import { MediaInfo, UnmappedMedia } from '../../../models';
+import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
 import { DashboardMessage } from '../../DashboardMessage';
 import { useRecoilValue } from 'recoil';
 import { PageSelector, SelectedMediaFolderSelector } from '../../state';
-import useThemeColors from '../../hooks/useThemeColors';
 import { DetailsItem } from './DetailsItem';
 import { DetailsInput } from './DetailsInput';
 import * as l10n from '@vscode/l10n';
@@ -24,6 +23,7 @@ export interface IDetailsSlideOverProps {
   media: MediaInfo;
   showForm: boolean;
   isImageFile: boolean;
+  isVideoFile: boolean;
   onEdit: () => void;
   onEditClose: () => void;
   onDismiss: () => void;
@@ -39,15 +39,16 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
   onEdit,
   onEditClose,
   onDismiss,
-  isImageFile
+  isImageFile,
+  isVideoFile
 }: React.PropsWithChildren<IDetailsSlideOverProps>) => {
   const [filename, setFilename] = React.useState<string>(media.filename);
   const [caption, setCaption] = React.useState<string | undefined>(media.caption);
   const [title, setTitle] = React.useState<string | undefined>(media.title);
+  const [unmapped, setUnmapped] = React.useState<UnmappedMedia[]>([]);
   const [alt, setAlt] = React.useState(media.alt);
   const selectedFolder = useRecoilValue(SelectedMediaFolderSelector);
   const page = useRecoilValue(PageSelector);
-  const { getColors } = useThemeColors();
 
   const createdDate = useMemo(() => DateHelper.tryParse(media.ctime), [media]);
   const modifiedDate = useMemo(() => DateHelper.tryParse(media.mtime), [media]);
@@ -70,6 +71,17 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
     onEditClose();
   }, [media, filename, caption, alt, title, selectedFolder, page]);
 
+  const remapMetadata = useCallback((item: UnmappedMedia) => {
+    Messenger.send(DashboardMessage.remapMediaMetadata, {
+      file: media.fsPath,
+      unmappedItem: item,
+      folder: selectedFolder,
+      page
+    });
+
+    onEditClose();
+  }, [media, filename, caption, alt, title, selectedFolder, page]);
+
   React.useEffect(() => {
     setTitle(media.title);
     setAlt(media.alt);
@@ -77,15 +89,21 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
     setFilename(media.filename);
   }, [media]);
 
+  React.useEffect(() => {
+    if (showForm) {
+      messageHandler.request<UnmappedMedia[]>(DashboardMessage.getUnmappedMedia, filename).then((result) => {
+        setUnmapped(result);
+      });
+    } else {
+      setUnmapped([]);
+    }
+  }, [showForm, filename]);
+
   return (
     <Transition.Root show={true} as={Fragment}>
       <Dialog onClose={onDismiss} as={'div' as any} className="fixed inset-0 overflow-hidden z-50">
         <div className="absolute inset-0 overflow-hidden">
-          <Dialog.Overlay className={`absolute inset-0 transition-opacity ${getColors(
-            'bg-vulcan-500 bg-opacity-75',
-            'bg-[var(--vscode-editor-background)] opacity-75'
-          )
-            }`} />
+          <Dialog.Overlay className={`absolute inset-0 transition-opacity bg-[var(--vscode-editor-background)] opacity-75`} />
 
           <div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
             <Transition.Child
@@ -98,28 +116,16 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
               leaveTo="translate-x-full"
             >
               <div className="pointer-events-auto w-screen max-w-md">
-                <div className={`flex h-full flex-col overflow-y-scroll border-l py-6 shadow-xl ${getColors(
-                  `bg-white dark:bg-vulcan-400 border-whisper-900 dark:border-vulcan-50`,
-                  `bg-[var(--vscode-sideBar-background)] border-[var(--frontmatter-border)]`
-                )
-                  }`}>
+                <div className={`flex h-full flex-col overflow-y-scroll border-l py-6 shadow-xl bg-[var(--vscode-sideBar-background)] border-[var(--frontmatter-border)]`}>
                   <div className="px-4 sm:px-6">
                     <div className="flex items-start justify-between">
-                      <Dialog.Title className={`text-lg font-medium ${getColors(
-                        'text-vulcan-300 dark:text-whisper-900',
-                        'text-[var(--vscode-editor-foreground)]'
-                      )
-                        }`}>
+                      <Dialog.Title className={`text-lg font-medium text-[var(--vscode-editor-foreground)]`}>
                         {l10n.t(LocalizationKey.dashboardMediaDialogTitle)}
                       </Dialog.Title>
                       <div className="ml-3 flex h-7 items-center">
                         <button
                           type="button"
-                          className={`focus:outline-none ${getColors(
-                            'text-vulcan-300 dark:text-whisper-900 hover:text-vulcan-500 dark:hover:text-whisper-500',
-                            'text-[var(--vscode-titleBar-inactiveForeground)] hover:text-[var(--vscode-titleBar-activeForeground)]'
-                          )
-                            }`}
+                          className={`focus:outline-none text-[var(--vscode-titleBar-inactiveForeground)] hover:text-[var(--vscode-titleBar-activeForeground)]`}
                           onClick={onDismiss}
                         >
                           <span className="sr-only">{l10n.t(LocalizationKey.dashboardMediaPanelClose)}</span>
@@ -132,29 +138,27 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
                   <div className="relative mt-6 flex-1 px-4 sm:px-6">
                     <div className="absolute inset-0 px-4 sm:px-6 space-y-8">
                       <div>
-                        {isImageFile && (
-                          <div className={`block w-full aspect-w-10 aspect-h-7 overflow-hidden border rounded ${getColors(
-                            'border-gray-200 dark:border-vulcan-200',
-                            'border-[var(--frontmatter-border)] bg-[var(--vscode-editor-background)]'
-                          )
-                            }`}>
-                            <img src={imgSrc} alt={media.filename} className="object-cover max-h-[300px] mx-auto" />
+                        {(isImageFile || isVideoFile) && (
+                          <div className={`block w-full aspect-w-10 aspect-h-7 overflow-hidden border rounded border-[var(--frontmatter-border)] bg-[var(--vscode-editor-background)]`}>
+                            {
+                              isImageFile && (
+                                <img src={imgSrc} alt={media.filename} className="object-cover max-h-[300px] mx-auto" />
+                              )
+                            }
+
+                            {
+                              isVideoFile && (
+                                <video src={media.vsPath} className="mx-auto object-cover" controls muted />
+                              )
+                            }
                           </div>
                         )}
                         <div className="mt-4 flex items-start justify-between">
                           <div>
-                            <h2 className={`text-lg font-medium ${getColors(
-                              'text-vulcan-300 dark:text-whisper-500',
-                              'text-[var(--vscode-foreground)]'
-                            )
-                              }`}>
+                            <h2 className={`text-lg font-medium text-[var(--vscode-foreground)]`}>
                               {media.filename}
                             </h2>
-                            <p className={`text-sm font-medium ${getColors(
-                              'text-vulcan-100 dark:text-whisper-900',
-                              'text-[var(--vscode-editor-foreground)]'
-                            )
-                              }`}>
+                            <p className={`text-sm font-medium text-[var(--vscode-editor-foreground)]`}>
                               {size}
                             </p>
                           </div>
@@ -165,44 +169,53 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
                         {/* EDIT METADATA FORM */}
                         {showForm && (
                           <>
-                            <h3 className={`text-base  ${getColors(
-                              'text-vulcan-300 dark:text-whisper-500',
-                              'text-[var(--vscode-editor-foreground)]'
-                            )
-                              }`}>
+                            <h3 className={`text-base text-[var(--vscode-editor-foreground)]`}>
                               {l10n.t(LocalizationKey.dashboardMediaMetadataPanelTitle)}
                             </h3>
-                            <p className={`text-sm font-medium ${getColors(
-                              'text-vulcan-100 dark:text-whisper-900',
-                              'text-[var(--vscode-editor-foreground)]'
-                            )
-                              }`}>
+
+                            {
+                              unmapped && unmapped.length > 0 && (
+                                <div className="flex flex-col py-3 space-y-3">
+                                  <p className={`text-sm my-3 font-medium text-[var(--vscode-editor-foreground)] opacity-90`}>
+                                    {l10n.t(LocalizationKey.dashboardMediaDetailsSlideOverUnmappedDescription)}
+                                  </p>
+                                  <ul className='pl-4'>
+                                    {
+                                      unmapped.map((item) => (
+                                        <li className='list-disc'>
+                                          <button
+                                            key={item.file}
+                                            className='text-left hover:text-[var(--frontmatter-link-hover)]'
+                                            onClick={() => remapMetadata(item)}>
+                                            {item.file}{item.metadata.title ? ` (${item.metadata.title})` : ''}
+                                          </button>
+                                        </li>
+                                      ))
+                                    }
+                                  </ul>
+                                </div>
+                              )
+                            }
+
+                            <p className={`text-sm my-3 font-medium text-[var(--vscode-editor-foreground)] opacity-90`}>
                               {l10n.t(LocalizationKey.dashboardMediaMetadataPanelDescription)}
                             </p>
                             <div className="flex flex-col py-3 space-y-3">
                               <div>
-                                <label className={`block text-sm font-medium  ${getColors(
-                                  'text-gray-700 dark:text-whisper-900',
-                                  'text-[var(--vscode-editor-foreground)]'
-                                )
-                                  }`}>
+                                <label className={`block text-sm font-medium text-[var(--vscode-editor-foreground)]`}>
                                   {l10n.t(LocalizationKey.dashboardMediaMetadataPanelFieldFileName)}
                                 </label>
                                 <div className="relative mt-1">
                                   <DetailsInput value={name || ""} onChange={(e) => setFilename(`${e.target.value}.${extension}`)} />
 
                                   <div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
-                                    <span className={`sm:text-sm ${getColors('text-gray-500', 'placeholder-[var(--vscode-input-placeholderForeground)]')}`}>.{extension}</span>
+                                    <span className={`sm:text-sm placeholder-[var(--vscode-input-placeholderForeground)]`}>.{extension}</span>
                                   </div>
                                 </div>
                               </div>
 
                               <div>
-                                <label className={`block text-sm font-medium ${getColors(
-                                  'text-gray-700 dark:text-whisper-900',
-                                  'text-[var(--vscode-editor-foreground)]'
-                                )
-                                  }`}>
+                                <label className={`block text-sm font-medium text-[var(--vscode-editor-foreground)]`}>
                                   {l10n.t(LocalizationKey.dashboardMediaCommonTitle)}
                                 </label>
                                 <div className="mt-1">
@@ -210,44 +223,32 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
                                 </div>
                               </div>
 
-                              {isImageFile && (
-                                <>
-                                  <div>
-                                    <label className={`block text-sm font-medium ${getColors(
-                                      'text-gray-700 dark:text-whisper-900',
-                                      'text-[var(--vscode-editor-foreground)]'
-                                    )
-                                      }`}>
-                                      {l10n.t(LocalizationKey.dashboardMediaCommonCaption)}
-                                    </label>
-                                    <div className="mt-1">
-                                      <DetailsInput value={caption || ""} onChange={(e) => setCaption(e.target.value)} isTextArea />
-                                    </div>
+                              {(isImageFile || isVideoFile) && (
+                                <div>
+                                  <label className={`block text-sm font-medium text-[var(--vscode-editor-foreground)]`}>
+                                    {l10n.t(LocalizationKey.dashboardMediaCommonCaption)}
+                                  </label>
+                                  <div className="mt-1">
+                                    <DetailsInput value={caption || ""} onChange={(e) => setCaption(e.target.value)} isTextArea />
                                   </div>
-                                  <div>
-                                    <label className={`block text-sm font-medium ${getColors(
-                                      'text-gray-700 dark:text-whisper-900',
-                                      'text-[var(--vscode-editor-foreground)]'
-                                    )
-                                      }`}>
-                                      {l10n.t(LocalizationKey.dashboardMediaCommonAlt)}
-                                    </label>
-                                    <div className="mt-1">
-                                      <DetailsInput value={alt || ""} onChange={(e) => setAlt(e.target.value)} isTextArea />
-                                    </div>
+                                </div>
+                              )}
+                              {isImageFile && (
+                                <div>
+                                  <label className={`block text-sm font-medium text-[var(--vscode-editor-foreground)]`}>
+                                    {l10n.t(LocalizationKey.dashboardMediaCommonAlt)}
+                                  </label>
+                                  <div className="mt-1">
+                                    <DetailsInput value={alt || ""} onChange={(e) => setAlt(e.target.value)} isTextArea />
                                   </div>
-                                </>
+                                </div>
                               )}
                             </div>
 
                             <div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
                               <button
                                 type="button"
-                                className={`w-full inline-flex justify-center rounded border-transparent shadow-sm px-4 py-2 text-base font-medium sm:ml-3 sm:w-auto sm:text-sm disabled:opacity-30 ${getColors(
-                                  'border focus:outline-none focus:ring-2 focus:ring-offset-2 text-white bg-teal-600 hover:bg-teal-700 dark:hover:bg-teal-900 focus:ring-teal-500',
-                                  'bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] text-[var(--vscode-button-foreground)] outline-[var(--vscode-focusBorder)] outline-1'
-                                )
-                                  }`}
+                                className={`w-full inline-flex justify-center rounded border-transparent shadow-sm px-4 py-2 text-base font-medium sm:ml-3 sm:w-auto sm:text-sm disabled:opacity-30 bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] text-[var(--vscode-button-foreground)] outline-[var(--vscode-focusBorder)] outline-1`}
                                 onClick={onSubmitMetadata}
                                 disabled={!filename}
                               >
@@ -255,11 +256,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
                               </button>
                               <button
                                 type="button"
-                                className={`mt-3 w-full inline-flex justify-center rounded shadow-sm px-4 py-2 text-base font-medium focus:outline-none sm:mt-0 sm:w-auto sm:text-sm ${getColors(
-                                  'border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 dark:hover:bg-gray-200',
-                                  'bg-[var(--vscode-button-secondaryBackground)] hover:bg-[var(--vscode-button-secondaryHoverBackground)] text-[var(--vscode-button-secondaryForeground)]'
-                                )
-                                  }`}
+                                className={`mt-3 w-full inline-flex justify-center rounded shadow-sm px-4 py-2 text-base font-medium focus:outline-none sm:mt-0 sm:w-auto sm:text-sm bg-[var(--vscode-button-secondaryBackground)] hover:bg-[var(--vscode-button-secondaryHoverBackground)] text-[var(--vscode-button-secondaryForeground)]`}
                                 onClick={onEditClose}
                               >
                                 {l10n.t(LocalizationKey.commonCancel)}
@@ -270,22 +267,14 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
 
                         {!showForm && (
                           <>
-                            <h3 className={`text-base flex items-center ${getColors(
-                              'text-vulcan-300 dark:text-whisper-500',
-                              'text-[var(--vscode-foreground)]'
-                            )
-                              }`}>
+                            <h3 className={`text-base flex items-center text-[var(--vscode-foreground)]`}>
                               <span>{l10n.t(LocalizationKey.dashboardMediaMetadataPanelFormMetadataTitle)}</span>
                               <button onClick={onEdit}>
                                 <PencilAltIcon className="w-4 h-4 ml-2" aria-hidden="true" />
                                 <span className="sr-only">{l10n.t(LocalizationKey.commonEdit)}</span>
                               </button>
                             </h3>
-                            <dl className={`mt-2 border-t border-b divide-y ${getColors(
-                              'border-gray-200 dark:border-vulcan-200 divide-gray-200 dark:divide-vulcan-200',
-                              'border-[var(--frontmatter-border)] divide-[var(--frontmatter-border)]'
-                            )
-                              }`}>
+                            <dl className={`mt-2 border-t border-b divide-y border-[var(--frontmatter-border)] divide-[var(--frontmatter-border)]`}>
                               <DetailsItem title={l10n.t(LocalizationKey.dashboardMediaMetadataPanelFieldFileName)} details={media.filename} />
                               <DetailsItem title={l10n.t(LocalizationKey.dashboardMediaCommonTitle)} details={media.title || ""} />
 
@@ -302,18 +291,10 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
 
                       {!showForm && (
                         <div>
-                          <h3 className={`text-base ${getColors(
-                            'text-vulcan-300 dark:text-whisper-500',
-                            'text-[var(--vscode-foreground)]'
-                          )
-                            }`}>
+                          <h3 className={`text-base text-[var(--vscode-foreground)]`}>
                             {l10n.t(LocalizationKey.dashboardMediaMetadataPanelFormInformationTitle)}
                           </h3>
-                          <dl className={`mt-2 border-t border-b divide-y ${getColors(
-                            'border-gray-200 dark:border-vulcan-200 divide-gray-200 dark:divide-vulcan-200',
-                            'border-[var(--frontmatter-border)] divide-[var(--frontmatter-border)]'
-                          )
-                            }`}>
+                          <dl className={`mt-2 border-t border-b divide-y border-[var(--frontmatter-border)] divide-[var(--frontmatter-border)]`}>
                             {createdDate && (
                               <DetailsItem title={l10n.t(LocalizationKey.dashboardMediaMetadataPanelFormInformationCreatedDate)} details={format(createdDate, 'MMM dd, yyyy')} />
                             )}
diff --git a/src/dashboardWebView/components/Media/Item.tsx b/src/dashboardWebView/components/Media/Item.tsx
index a5a00175..55d12c9a 100644
--- a/src/dashboardWebView/components/Media/Item.tsx
+++ b/src/dashboardWebView/components/Media/Item.tsx
@@ -433,18 +433,9 @@ export const Item: React.FunctionComponent<IItemProps> = ({
 
   return (
     <>
-      <li className={`group relative shadow-md hover:shadow-xl dark:shadow-none border rounded ${getColors(
-        'bg-gray-50 dark:bg-vulcan-200 dark:hover:bg-vulcan-100 border-gray-200 dark:border-vulcan-50',
-        'bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-sideBarTitle-foreground)] border-[var(--frontmatter-border)]'
-      )
-        }`}>
+      <li className={`group relative shadow-md hover:shadow-xl dark:shadow-none border rounded bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-sideBarTitle-foreground)] border-[var(--frontmatter-border)]`}>
         <button
-          className={`group/button relative block w-full aspect-w-10 aspect-h-7 overflow-hidden h-48 ${isImageFile ? 'cursor-pointer' : 'cursor-default'
-            } ${getColors(
-              `bg-gray-200 dark:bg-vulcan-300`,
-              `border-b border-[var(--frontmatter-border)]`
-            )
-            }`}
+          className={`group/button relative block w-full aspect-w-10 aspect-h-7 overflow-hidden h-48 ${isImageFile ? 'cursor-pointer' : 'cursor-default'} border-b border-[var(--frontmatter-border)]`}
           onClick={hasViewData ? undefined : openLightbox}
         >
           <div
@@ -459,11 +450,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
           </div>
           {hasViewData && (
             <div
-              className={`hidden group-hover/button:flex absolute top-0 right-0 bottom-0 left-0 items-center justify-center ${getColors(
-                `bg-vulcan-500 bg-opacity-70`,
-                `bg-black bg-opacity-90`
-              )
-                }`}
+              className={`hidden group-hover/button:flex absolute top-0 right-0 bottom-0 left-0 items-center justify-center bg-black bg-opacity-70`}
             >
               <div
                 className={`h-full ${showMediaSnippet ? 'w-1/3' : 'w-full'
@@ -471,7 +458,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
               >
                 <button
                   title="Insert image"
-                  className={`h-1/3 ${getColors(`text-gray-300 hover:text-teal-600`, `text-[var(--vscode-editor-foreground)] hover:text-[var(--vscode-button-hoverBackground)]`)}`}
+                  className={`h-1/3 text-white hover:text-[var(--vscode-button-background)]`}
                   onClick={insertToArticle}
                 >
                   <PlusIcon className={`w-full h-full hover:drop-shadow-md `} aria-hidden="true" />
@@ -481,7 +468,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
                 <div className={`h-full w-1/3 flex items-center justify-center`}>
                   <button
                     title="Insert snippet"
-                    className={`h-1/3 ${getColors(`text-gray-300 hover:text-teal-600`, `text-[var(--vscode-editor-foreground)] hover:text-[var(--vscode-button-hoverBackground)]`)}`}
+                    className={`h-1/3 text-white hover:text-[var(--vscode-button-background)]`}
                     onClick={insertSnippet}
                   >
                     <CodeIcon
@@ -714,6 +701,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
           media={media}
           showForm={showForm}
           isImageFile={isImageFile}
+          isVideoFile={isVideoFile}
           onEdit={() => setShowForm(true)}
           onEditClose={() => setShowForm(false)}
           onDismiss={() => {
diff --git a/src/dashboardWebView/components/Media/Media.tsx b/src/dashboardWebView/components/Media/Media.tsx
index 8eace8e2..9267d7e1 100644
--- a/src/dashboardWebView/components/Media/Media.tsx
+++ b/src/dashboardWebView/components/Media/Media.tsx
@@ -1,8 +1,9 @@
 import { Messenger } from '@estruyf/vscode/dist/client';
 import { UploadIcon } from '@heroicons/react/outline';
 import * as React from 'react';
-import { useRecoilValue } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
 import {
+  DashboardViewAtom,
   LoadingAtom,
   MediaFoldersAtom,
   SelectedMediaFolderAtom,
@@ -28,6 +29,7 @@ import { MediaInfo } from '../../../models';
 import useThemeColors from '../../hooks/useThemeColors';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { NavigationType } from '../../models';
 
 export interface IMediaProps { }
 
@@ -41,6 +43,7 @@ export const Media: React.FunctionComponent<IMediaProps> = (
   const folders = useRecoilValue(MediaFoldersAtom);
   const loading = useRecoilValue(LoadingAtom);
   const { getColors } = useThemeColors();
+  const [, setView] = useRecoilState(DashboardViewAtom);
 
   const currentStaticFolder = useMemo(() => {
     if (settings?.staticFolder) {
@@ -150,6 +153,7 @@ export const Media: React.FunctionComponent<IMediaProps> = (
   );
 
   useEffect(() => {
+    setView(NavigationType.Media);
     Messenger.send(DashboardMessage.sendTelemetry, {
       event: TelemetryEvent.webviewMediaView
     });
diff --git a/src/dashboardWebView/components/SettingsView/CommonSettings.tsx b/src/dashboardWebView/components/SettingsView/CommonSettings.tsx
new file mode 100644
index 00000000..33c2ce91
--- /dev/null
+++ b/src/dashboardWebView/components/SettingsView/CommonSettings.tsx
@@ -0,0 +1,121 @@
+import * as React from 'react';
+import * as l10n from '@vscode/l10n';
+import { LocalizationKey } from '../../../localization';
+import { Startup } from '../Header/Startup';
+import { useRecoilValue } from 'recoil';
+import { SettingsSelector } from '../../state';
+import { SettingsInput } from './SettingsInput';
+import { VSCodeButton } from '@vscode/webview-ui-toolkit/react';
+import { FrameworkDetectors, SETTING_FRAMEWORK_START, SETTING_PREVIEW_HOST, SETTING_WEBSITE_URL } from '../../../constants';
+import { messageHandler } from '@estruyf/vscode/dist/client';
+import { DashboardMessage } from '../../DashboardMessage';
+
+export interface ICommonSettingsProps { }
+
+interface Config {
+  name: string;
+  value: string;
+}
+
+export const CommonSettings: React.FunctionComponent<ICommonSettingsProps> = (props: React.PropsWithChildren<ICommonSettingsProps>) => {
+  const settings = useRecoilValue(SettingsSelector);
+  const [config, setConfig] = React.useState<Config[]>([]);
+  const [updated, setUpdated] = React.useState<boolean>(false);
+
+  const onSettingChange = React.useCallback((name: string, value: string) => {
+    setConfig((prev) => {
+      const setting = prev.find((c) => c.name === name);
+      if (setting) {
+        setting.value = value;
+      } else {
+        prev.push({
+          name,
+          value
+        });
+      }
+      return [...prev];
+    });
+    setUpdated(true);
+  }, [config]);
+
+  const retrieveSettings = () => {
+    messageHandler.request<Config[]>(DashboardMessage.getSettings, [SETTING_PREVIEW_HOST, SETTING_WEBSITE_URL, SETTING_FRAMEWORK_START]).then((config) => {
+      setConfig(config);
+      setUpdated(false);
+    });
+  }
+
+  const saveSettings = React.useCallback(() => {
+    messageHandler.request(DashboardMessage.setSettings, config).then(() => {
+      retrieveSettings();
+    });
+  }, [config])
+
+  React.useEffect(() => {
+    if (settings?.lastUpdated) {
+      retrieveSettings();
+    }
+  }, [settings?.lastUpdated]);
+
+  return (
+    <div className='w-full divide-y divide-[var(--frontmatter-border)]'>
+      <div className='py-4'>
+        <h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsOpenOnStartup)}</h2>
+
+        <Startup settings={settings} />
+      </div>
+
+      <div className='py-4'>
+        <h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsCommonSettingsWebsiteTitle)}</h2>
+
+        <div className='space-y-2'>
+          <SettingsInput
+            label={l10n.t(LocalizationKey.settingsCommonSettingsPreviewUrl)}
+            name={SETTING_PREVIEW_HOST}
+            value={config.find((c) => c.name === SETTING_PREVIEW_HOST)?.value || ""}
+            onChange={onSettingChange}
+          />
+
+          <SettingsInput
+            label={l10n.t(LocalizationKey.settingsCommonSettingsWebsiteUrl)}
+            name={SETTING_WEBSITE_URL}
+            value={config.find((c) => c.name === SETTING_WEBSITE_URL)?.value || ""}
+            onChange={onSettingChange}
+          />
+
+          <SettingsInput
+            label={l10n.t(LocalizationKey.settingsCommonSettingsStartCommand)}
+            name={SETTING_FRAMEWORK_START}
+            value={config.find((c) => c.name === SETTING_FRAMEWORK_START)?.value || ""}
+            onChange={onSettingChange}
+            fallback={FrameworkDetectors.find((f) => f.framework.name === settings?.crntFramework)?.commands.start || ""}
+          />
+
+          <div className={`mt-4 flex gap-2`}>
+            <VSCodeButton appearance="secondary" onClick={retrieveSettings}>
+              {l10n.t(LocalizationKey.commonCancel)}
+            </VSCodeButton>
+            <VSCodeButton disabled={!updated} onClick={saveSettings}>
+              {l10n.t(LocalizationKey.commonSave)}
+            </VSCodeButton>
+          </div>
+        </div>
+      </div>
+      <div className='py-4 space-y-2'>
+        <h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsDiagnostic)}</h2>
+
+        <p>{l10n.t(LocalizationKey.settingsDiagnosticDescription)}</p>
+
+        <p>
+          <a
+            href={`command:frontMatter.diagnostics`}
+            title={l10n.t(LocalizationKey.settingsDiagnosticLink)}
+            className='text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]'
+          >
+            {l10n.t(LocalizationKey.settingsDiagnosticLink)}
+          </a>
+        </p>
+      </div>
+    </div>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/SettingsView/SettingsInput.tsx b/src/dashboardWebView/components/SettingsView/SettingsInput.tsx
new file mode 100644
index 00000000..6785cc37
--- /dev/null
+++ b/src/dashboardWebView/components/SettingsView/SettingsInput.tsx
@@ -0,0 +1,31 @@
+import { VSCodeTextField } from '@vscode/webview-ui-toolkit/react';
+import * as React from 'react';
+
+export interface ISettingsInputProps {
+  label: string;
+  name: string;
+  value: string;
+  onChange: (key: string, value: string) => void;
+  fallback?: string;
+}
+
+export const SettingsInput: React.FunctionComponent<ISettingsInputProps> = ({
+  label,
+  name,
+  value,
+  onChange,
+  fallback
+}: React.PropsWithChildren<ISettingsInputProps>) => {
+
+  return (
+    <VSCodeTextField
+      className='w-full p-0 m-0 bg-inherit border-0 focus:border-0 outline-none focus:outline-none shadow-none'
+      style={{
+        boxShadow: 'none'
+      }}
+      value={value || fallback || ""}
+      onInput={(e: React.ChangeEvent<HTMLInputElement>) => onChange(name, e.target.value)}>
+      {label}
+    </VSCodeTextField>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/SettingsView/SettingsLink.tsx b/src/dashboardWebView/components/SettingsView/SettingsLink.tsx
new file mode 100644
index 00000000..b5773d72
--- /dev/null
+++ b/src/dashboardWebView/components/SettingsView/SettingsLink.tsx
@@ -0,0 +1,30 @@
+import * as React from 'react';
+import { useRecoilValue } from 'recoil';
+import { SettingsSelector } from '../../state';
+import { CogIcon } from '@heroicons/react/solid';
+import { NavigationType } from '../../models';
+
+export interface ISettingsLinkProps {
+  onNavigate: (navigationType: NavigationType) => void;
+}
+
+export const SettingsLink: React.FunctionComponent<ISettingsLinkProps> = ({
+  onNavigate
+}: React.PropsWithChildren<ISettingsLinkProps>) => {
+  const settings = useRecoilValue(SettingsSelector);
+
+  if (!settings) {
+    return null;
+  }
+
+  return (
+    <button
+      className="flex items-center mr-4 hover:text-[var(--vscode-textLink-activeForeground)]"
+      title={`Settings`}
+      onClick={() => onNavigate(NavigationType.Settings)}
+    >
+      <CogIcon className="h-4 w-4" />
+      <span className='sr-only'>Settings</span>
+    </button>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/SettingsView/SettingsView.tsx b/src/dashboardWebView/components/SettingsView/SettingsView.tsx
new file mode 100644
index 00000000..fc481240
--- /dev/null
+++ b/src/dashboardWebView/components/SettingsView/SettingsView.tsx
@@ -0,0 +1,98 @@
+import * as React from 'react';
+import { PageLayout } from '../Layout';
+import { SponsorMsg } from '../Layout/SponsorMsg';
+import { useRecoilValue } from 'recoil';
+import { SettingsSelector } from '../../state';
+import { Spinner } from '../Common/Spinner';
+import { AstroContentTypes } from '../Configuration/Astro/AstroContentTypes';
+import { ContentFolders } from '../Configuration/Common/ContentFolders';
+import * as l10n from '@vscode/l10n';
+import { LocalizationKey } from '../../../localization';
+import { COMMAND_NAME } from '../../../constants';
+import { RefreshIcon } from '@heroicons/react/outline';
+import { VSCodePanelTab, VSCodePanelView, VSCodePanels } from '@vscode/webview-ui-toolkit/react';
+import { CommonSettings } from './CommonSettings';
+
+export interface ISettingsViewProps { }
+
+export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: React.PropsWithChildren<ISettingsViewProps>) => {
+  const [loading, setLoading] = React.useState<boolean>(false);
+  const settings = useRecoilValue(SettingsSelector);
+
+  return (
+    <PageLayout>
+      {
+        loading && <Spinner />
+      }
+
+      {
+        settings && (
+          <div className='mx-auto max-w-7xl w-full'>
+            <div className='flex items-center justify-between'>
+              <h1 className='text-3xl'>{l10n.t(LocalizationKey.commonSettings)}</h1>
+
+              <a
+                type="button"
+                className={`inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium focus:outline-none rounded text-[var(--vscode-button-foreground)] hover:text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`}
+                href={`command:${COMMAND_NAME.settingsRefresh}`}
+              >
+                <RefreshIcon
+                  className={`w-4 h-4 mr-2`}
+                  aria-hidden="true"
+                />
+                <span>{l10n.t(LocalizationKey.commonRefreshSettings)}</span>
+              </a>
+            </div>
+
+            <VSCodePanels className={`mt-4`}>
+              <VSCodePanelTab id="view-1">{l10n.t(LocalizationKey.settingsViewCommon)}</VSCodePanelTab>
+              <VSCodePanelTab id="view-2">{l10n.t(LocalizationKey.settingsViewContentFolders)}</VSCodePanelTab>
+
+              {
+                settings?.crntFramework === 'astro' && (
+                  <VSCodePanelTab id="view-3">{l10n.t(LocalizationKey.settingsViewAstro)}</VSCodePanelTab>
+                )
+              }
+
+              <VSCodePanelView id="view-1">
+                <CommonSettings />
+              </VSCodePanelView>
+
+              <VSCodePanelView id="view-2">
+                <div className='py-4'>
+                  <h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsContentFolders)}</h2>
+
+                  <ContentFolders
+                    settings={settings}
+                    triggerLoading={(isLoading) => setLoading(isLoading)} />
+                </div>
+              </VSCodePanelView>
+
+              {
+                settings?.crntFramework === 'astro' && (
+                  <VSCodePanelView id="view-3">
+                    <div className='py-4'>
+                      <h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsContentTypes)}</h2>
+
+                      <AstroContentTypes
+                        settings={settings}
+                        triggerLoading={(isLoading) => setLoading(isLoading)} />
+                    </div>
+                  </VSCodePanelView>
+                )
+              }
+            </VSCodePanels>
+          </div>
+        )
+      }
+
+      <SponsorMsg
+        beta={settings?.beta}
+        version={settings?.versionInfo}
+        isBacker={settings?.isBacker}
+      />
+
+      <img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=settings" alt="Settings metrics" />
+    </PageLayout >
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/SnippetsView/Snippets.tsx b/src/dashboardWebView/components/SnippetsView/Snippets.tsx
index 75e96b05..83d5a409 100644
--- a/src/dashboardWebView/components/SnippetsView/Snippets.tsx
+++ b/src/dashboardWebView/components/SnippetsView/Snippets.tsx
@@ -2,14 +2,14 @@ import { Messenger } from '@estruyf/vscode/dist/client';
 import { CodeIcon, PlusSmIcon } from '@heroicons/react/outline';
 import * as React from 'react';
 import { useCallback, useEffect, useMemo, useState } from 'react';
-import { useRecoilValue } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
 import { FeatureFlag } from '../../../components/features/FeatureFlag';
 import { FEATURE_FLAG } from '../../../constants';
 import { TelemetryEvent } from '../../../constants/TelemetryEvent';
 import { SnippetParser } from '../../../helpers/SnippetParser';
 import { DashboardMessage } from '../../DashboardMessage';
 import useThemeColors from '../../hooks/useThemeColors';
-import { ModeAtom, SettingsSelector, ViewDataSelector } from '../../state';
+import { DashboardViewAtom, ModeAtom, SettingsSelector, ViewDataSelector } from '../../state';
 import { FilterInput } from '../Header/FilterInput';
 import { PageLayout } from '../Layout/PageLayout';
 import { FormDialog } from '../Modals/FormDialog';
@@ -18,6 +18,7 @@ import { Item } from './Item';
 import { NewForm } from './NewForm';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { NavigationType } from '../../models';
 
 export interface ISnippetsProps { }
 
@@ -34,6 +35,7 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
   const [mediaSnippet, setMediaSnippet] = useState(false);
   const [snippetFilter, setSnippetFilter] = useState<string>('');
   const { getColors } = useThemeColors();
+  const [, setView] = useRecoilState(DashboardViewAtom);
 
   const snippets = settings?.snippets || {};
   const snippetKeys = useMemo(() => {
@@ -82,6 +84,7 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
   };
 
   useEffect(() => {
+    setView(NavigationType.Snippets);
     Messenger.send(DashboardMessage.sendTelemetry, {
       event: TelemetryEvent.webviewSnippetsView
     });
diff --git a/src/dashboardWebView/components/Steps/SelectItem.tsx b/src/dashboardWebView/components/Steps/SelectItem.tsx
index 21de3191..0adbc032 100644
--- a/src/dashboardWebView/components/Steps/SelectItem.tsx
+++ b/src/dashboardWebView/components/Steps/SelectItem.tsx
@@ -7,6 +7,7 @@ export interface ISelectItemProps {
   icon?: "add" | "select";
   buttonTitle: string;
   isSelected: boolean;
+  disabled?: boolean;
   onClick: () => void;
 }
 
@@ -15,6 +16,7 @@ export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
   icon = "select",
   buttonTitle,
   isSelected,
+  disabled,
   onClick
 }: React.PropsWithChildren<ISelectItemProps>) => {
   return (
@@ -23,8 +25,9 @@ export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
     >
       <button
         onClick={onClick}
-        className={`mr-2 flex gap-2 items-center hover:text-[var(--vscode-textLink-activeForeground)]`}
+        className={`mr-2 flex gap-2 items-center hover:text-[var(--vscode-textLink-activeForeground)] disabled:cursor-not-allowed`}
         title={buttonTitle}
+        disabled={disabled}
       >
         {isSelected ? (
           icon === "add" ? (
diff --git a/src/dashboardWebView/components/Steps/Step.tsx b/src/dashboardWebView/components/Steps/Step.tsx
index 2fe3f99c..ddd66487 100644
--- a/src/dashboardWebView/components/Steps/Step.tsx
+++ b/src/dashboardWebView/components/Steps/Step.tsx
@@ -1,6 +1,5 @@
 import { CheckIcon } from '@heroicons/react/outline';
 import * as React from 'react';
-import useThemeColors from '../../hooks/useThemeColors';
 import { Status } from '../../models/Status';
 
 export interface IStepProps {
@@ -18,67 +17,46 @@ export const Step: React.FunctionComponent<IStepProps> = ({
   showLine,
   onClick
 }: React.PropsWithChildren<IStepProps>) => {
-  const { getColors } = useThemeColors();
 
   const renderChildren = () => {
     return (
       <>
         {status === Status.NotStarted && (
-          <span className="h-9 flex items-center" aria-hidden="true">
-            <span
-              className={`relative z-10 w-8 h-8 flex items-center justify-center border-2 rounded-full bg-[var(--frontmatter-border)] border-[var(--frontmatter-border)] ${onClick ? getColors('group-hover:text-gray-400', 'group-hover:text-[var(--vscode-button-foreground)] group-hover:border-[var(--vscode-button-hoverBackground)]') : ''
+          <div className="h-9 flex items-center" aria-hidden="true">
+            <div
+              className={`relative z-10 w-8 h-8 flex items-center justify-center border-2 rounded-full bg-[var(--frontmatter-border)] border-[var(--frontmatter-border)] ${onClick ? 'group-hover:text-[var(--vscode-button-foreground)] group-hover:border-[var(--vscode-button-hoverBackground)]' : ''
                 }`}
             >
               <span
-                className={`h-2.5 w-2.5 bg-transparent rounded-full ${onClick ? getColors('group-hover:bg-gray-400', 'group-hover:bg-[var(--vscode-button-hoverBackground)]') : ''
+                className={`h-2.5 w-2.5 bg-transparent rounded-full ${onClick ? 'group-hover:bg-[var(--vscode-button-hoverBackground)]' : ''
                   }`}
               />
-            </span>
-          </span>
+            </div>
+          </div>
         )}
 
-        {status === Status.Active && (
-          <span className="h-9 flex items-center" aria-hidden="true">
-            <span className={`relative z-10 w-8 h-8 flex items-center justify-center border-2 rounded-full ${getColors(
-              'bg-white border-teal-600',
-              'bg-[var(--frontmatter-border)] border-[var(--frontmatter-border)] group-hover:text-[var(--vscode-button-foreground)] group-hover:border-[var(--vscode-button-hoverBackground)]'
-            )
-              }`}>
-              <span className={`h-2.5 w-2.5 rounded-full ${getColors(
-                'bg-teal-600',
-                'bg-[var(--frontmatter-button-background)]'
-              )
-                }`} />
-            </span>
-          </span>
+        {(status === Status.Active || status === Status.Optional) && (
+          <div className="h-9 flex items-center" aria-hidden="true">
+            <div className={`relative z-10 w-8 h-8 flex items-center justify-center border-2 rounded-full bg-[var(--frontmatter-border)] border-[var(--frontmatter-border)] group-hover:text-[var(--vscode-button-foreground)] group-hover:border-[var(--vscode-button-hoverBackground)]`}>
+              <span className={`h-2.5 w-2.5 rounded-full bg-[var(--frontmatter-button-background)]`} />
+            </div>
+          </div>
         )}
 
         {status === Status.Completed && (
-          <span className="h-9 flex items-center">
-            <span className={`relative z-10 w-8 h-8 flex items-center justify-center rounded-full ${getColors(
-              'bg-teal-600 group-hover:bg-teal-800',
-              'text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] group-hover:bg-[var(--vscode-button-hoverBackground)]'
-            )
-              }`}>
-              <CheckIcon className={`w-5 h-5 ${getColors('text-white', '')}`} aria-hidden="true" />
-            </span>
-          </span>
+          <div className="h-9 flex items-center">
+            <div className={`relative z-10 w-8 h-8 flex items-center justify-center rounded-full text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] group-hover:bg-[var(--vscode-button-hoverBackground)]`}>
+              <CheckIcon className={`w-5 h-5`} aria-hidden="true" />
+            </div>
+          </div>
         )}
 
-        <span className={`ml-4 min-w-0 flex flex-col`}>
-          <span className={`text-xs font-semibold tracking-wide uppercase ${getColors(
-            'text-vulcan-500 dark:text-whisper-500',
-            'text-[var(--vscode-editor-foreground)]'
-          )
-            }`}>
+        <div className={`ml-4 flex flex-col w-full`}>
+          <div className={`text-xs font-semibold tracking-wide uppercase text-[var(--vscode-editor-foreground)]`}>
             {name}
-          </span>
-          <div className={`mt-1 text-sm ${getColors(
-            'text-vulcan-400 dark:text-whisper-600',
-            'text-[var(--vscode-editor-foreground)]'
-          )
-            }`}>{description}</div>
-        </span>
+          </div>
+          <div className={`mt-1 text-sm text-[var(--vscode-editor-foreground)]`}>{description}</div>
+        </div>
       </>
     );
   };
@@ -87,8 +65,7 @@ export const Step: React.FunctionComponent<IStepProps> = ({
     <>
       {showLine ? (
         <div
-          className={`-ml-px absolute mt-0.5 top-4 left-4 w-0.5 h-full ${status === Status.Completed ? getColors('bg-teal-600', 'bg-[var(--frontmatter-button-background)]') : getColors('bg-gray-300', 'bg-[var(--frontmatter-border)]')
-            }`}
+          className={`-ml-px absolute mt-0.5 top-4 left-4 w-0.5 h-full ${(status === Status.Completed || status === Status.Optional) ? 'bg-[var(--frontmatter-button-background)]' : 'bg-[var(--frontmatter-border)]'}`}
           aria-hidden="true"
         />
       ) : null}
diff --git a/src/dashboardWebView/components/Steps/StepsToGetStarted.tsx b/src/dashboardWebView/components/Steps/StepsToGetStarted.tsx
index 681a7699..7f4503f2 100644
--- a/src/dashboardWebView/components/Steps/StepsToGetStarted.tsx
+++ b/src/dashboardWebView/components/Steps/StepsToGetStarted.tsx
@@ -7,49 +7,27 @@ import { Step } from './Step';
 import { useMemo, useState } from 'react';
 import { Menu } from '@headlessui/react';
 import { MenuItem } from '../Menu';
-import { ContentFolder, Framework, StaticFolder, Template } from '../../../models';
+import { Framework, StaticFolder, Template } from '../../../models';
 import { ChevronDownIcon } from '@heroicons/react/outline';
 import { FrameworkDetectors } from '../../../constants/FrameworkDetectors';
-import { join } from 'path';
 import useThemeColors from '../../hooks/useThemeColors';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
 import { SelectItem } from './SelectItem';
 import { Templates } from '../../../constants';
+import { TemplateItem } from './TemplateItem';
+import { Spinner } from '../Common/Spinner';
+import { AstroContentTypes } from '../Configuration/Astro/AstroContentTypes';
+import { ContentFolders } from '../Configuration/Common/ContentFolders';
 
 export interface IStepsToGetStartedProps {
   settings: Settings;
 }
 
-const Folder = ({
-  wsFolder,
-  folder,
-  folders,
-  addFolder
-}: {
-  wsFolder: string;
-  folder: string;
-  folders: ContentFolder[];
-  addFolder: (folder: string) => void;
-}) => {
-
-  const isAdded = useMemo(
-    () => folders.find((f) => f.path.toLowerCase() === join(wsFolder, folder).toLowerCase()),
-    [folder, folders, wsFolder]
-  );
-
-  return (
-    <SelectItem
-      title={folder}
-      buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedButtonAddFolderTitle)}
-      isSelected={!!isAdded}
-      onClick={() => addFolder(folder)} />
-  );
-};
-
 export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps> = ({
   settings
 }: React.PropsWithChildren<IStepsToGetStartedProps>) => {
+  const [loading, setLoading] = useState<boolean>(false);
   const [framework, setFramework] = useState<string | null>(null);
   const [taxImported, setTaxImported] = useState<boolean>(false);
   const [templates, setTemplates] = useState<Template[]>([]);
@@ -62,16 +40,14 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
     Messenger.send(DashboardMessage.setFramework, framework);
   };
 
-  const addFolder = (folder: string) => {
-    Messenger.send(DashboardMessage.addFolder, folder);
-  };
-
   const addAssetFolder = (folder: string | StaticFolder) => {
     Messenger.send(DashboardMessage.addAssetsFolder, folder);
   }
 
   const triggerTemplate = (template: Template) => {
+    setLoading(true);
     messageHandler.request<boolean>(DashboardMessage.triggerTemplate, template).then((result) => {
+      setLoading(false);
       if (result) {
         reload();
       }
@@ -183,17 +159,18 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
         id: `welcome-template`,
         name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateName),
         description: (
-          <div className='mt-4'>
+          <div className=''>
             <div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateDescription)}</div>
-            <div className="mt-1 space-y-1">
+            <div className="mt-4 grid grid-cols-2 lg:grid-cols-3 gap-x-4 gap-y-4 w-full">
               {
                 crntTemplates && (crntTemplates || []).map(template => (
-                  <SelectItem
+                  <TemplateItem
                     key={template.name.toLowerCase().replace(/ /g, '-')}
                     title={template.name}
-                    icon='add'
+                    author={template.author}
+                    version={template.version}
+                    description={template.description}
                     buttonTitle={template.name}
-                    isSelected={false}
                     onClick={() => triggerTemplate(template)} />
                 ))
               }
@@ -201,13 +178,38 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
           </div>
         ),
         show: (crntTemplates || []).length > 0,
-        status: Status.Active,
+        status: Status.Optional,
+      },
+      {
+        id: `astro-content-types`,
+        name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAstroContentTypesName),
+        description: (
+          <AstroContentTypes
+            settings={settings}
+            triggerLoading={(isLoading) => setLoading(isLoading)} />
+        ),
+        show: settings.crntFramework === 'astro',
+        status: Status.Optional
+      },
+      {
+        id: `welcome-content-folders`,
+        name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersName),
+        description: (
+          <ContentFolders
+            settings={settings}
+            triggerLoading={(isLoading) => setLoading(isLoading)} />
+        ),
+        show: true,
+        status:
+          settings.contentFolders && settings.contentFolders.length > 0
+            ? Status.Completed
+            : Status.NotStarted
       },
       {
         id: `welcome-assets`,
         name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderName),
         description: (
-          <div className='mt-4'>
+          <div className='mt-1'>
             <div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderDescription)}</div>
             <div className="mt-1 space-y-1">
               <SelectItem
@@ -233,43 +235,6 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
         show: settings.crntFramework === 'astro' || framework === 'astro',
         status: settings.initialized && settings.staticFolder && settings.staticFolder !== "/" ? Status.Completed : Status.NotStarted,
       },
-      {
-        id: `welcome-content-folders`,
-        name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersName),
-        description: (
-          <>
-            <p>
-              {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersDescription)}
-            </p>
-
-            {settings?.dashboardState?.welcome?.contentFolders?.length > 0 && (
-              <div className="mt-4">
-                <div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersLabel)}</div>
-                <div className="mt-1 space-y-1">
-                  {settings?.dashboardState?.welcome?.contentFolders?.map((folder: string) => (
-                    <Folder
-                      key={folder}
-                      folder={folder}
-                      addFolder={addFolder}
-                      wsFolder={settings.wsFolder}
-                      folders={settings.contentFolders}
-                    />
-                  ))}
-                </div>
-              </div>
-            )}
-
-            <p className={`mt-4 ${getColors('text-vulcan-300 dark:text-gray-400', '')}`}>
-              <b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersInformationDescription)}.
-            </p>
-          </>
-        ),
-        show: true,
-        status:
-          settings.contentFolders && settings.contentFolders.length > 0
-            ? Status.Completed
-            : Status.NotStarted
-      },
       {
         id: `welcome-import`,
         name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsName),
@@ -321,6 +286,11 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
 
   return (
     <nav aria-label="Progress">
+      {
+        loading && (
+          <Spinner />
+        )
+      }
       <ol role="list">
         {steps.map((step, stepIdx) => (
           step.show && (
diff --git a/src/dashboardWebView/components/Steps/TemplateItem.tsx b/src/dashboardWebView/components/Steps/TemplateItem.tsx
new file mode 100644
index 00000000..d216e635
--- /dev/null
+++ b/src/dashboardWebView/components/Steps/TemplateItem.tsx
@@ -0,0 +1,38 @@
+import { UserIcon } from '@heroicons/react/outline';
+import { PuzzleIcon } from '@heroicons/react/solid';
+import * as React from 'react';
+
+export interface ITemplateItemProps {
+  title: string;
+  description: string;
+  author: string;
+  version: string;
+  buttonTitle: string;
+  onClick: () => void;
+}
+
+export const TemplateItem: React.FunctionComponent<ITemplateItemProps> = ({
+  title,
+  description,
+  author,
+  version,
+  buttonTitle,
+  onClick,
+}: React.PropsWithChildren<ITemplateItemProps>) => {
+  return (
+    <button
+      type='button'
+      onClick={onClick}
+      title={buttonTitle}
+      className='relative p-2 text-left space-y-2 rounded flex flex-col bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-editor-foreground)] border border-[var(--frontmatter-border)]'>
+      <h2 className='text-base'>{title}</h2>
+      <p className='text-sm'>{description}</p>
+      <div className='text-xs flex justify-between items-center w-full opacity-75'>
+        <span className='inline-flex items-center gap-1'><UserIcon className='inline w-3 h-3' /> {author}</span>
+        <span>v{version}</span>
+      </div>
+
+      <PuzzleIcon className='absolute top-0 right-2 h-8 w-8 opacity-25' />
+    </button>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/TaxonomyView/FilterInput.tsx b/src/dashboardWebView/components/TaxonomyView/FilterInput.tsx
new file mode 100644
index 00000000..5e370fcd
--- /dev/null
+++ b/src/dashboardWebView/components/TaxonomyView/FilterInput.tsx
@@ -0,0 +1,56 @@
+import { FilterIcon, XCircleIcon } from '@heroicons/react/outline';
+import * as React from 'react';
+
+export interface IFilterInputProps {
+  label?: string;
+  placeholder?: string;
+  value?: string;
+  disabled?: boolean;
+  onChange?: (value: string) => void;
+  onReset?: () => void;
+}
+
+export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
+  label,
+  placeholder,
+  value,
+  disabled,
+  onChange,
+  onReset,
+}: React.PropsWithChildren<IFilterInputProps>) => {
+  return (
+    <div className="flex space-x-4 flex-1">
+      <div className="min-w-0">
+        {
+          label && (
+            <label htmlFor="filter" className="sr-only">
+              {label}
+            </label>
+          )
+        }
+
+        <div className="relative flex justify-center">
+          <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+            <FilterIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
+          </div>
+
+          <input
+            type="text"
+            name="filter"
+            className={`block w-full py-2 pl-10 pr-3 sm:text-sm appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-editorWidget-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent`}
+            placeholder={placeholder || ""}
+            value={value}
+            onChange={(e) => onChange && onChange(e.target.value)}
+            disabled={disabled}
+          />
+
+          {value && (
+            <button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center">
+              <XCircleIcon className={`h-5 w-5 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
+            </button>
+          )}
+        </div>
+      </div>
+    </div>
+  );
+};
\ No newline at end of file
diff --git a/src/dashboardWebView/components/TaxonomyView/TaxonomyManager.tsx b/src/dashboardWebView/components/TaxonomyView/TaxonomyManager.tsx
index 3ec28d3e..269dc7eb 100644
--- a/src/dashboardWebView/components/TaxonomyView/TaxonomyManager.tsx
+++ b/src/dashboardWebView/components/TaxonomyView/TaxonomyManager.tsx
@@ -13,6 +13,9 @@ import { TaxonomyLookup } from './TaxonomyLookup';
 import useThemeColors from '../../hooks/useThemeColors';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { FilterInput } from './FilterInput';
+import { useDebounce } from '../../../hooks/useDebounce';
+import { usePrevious } from '../../../panelWebView/hooks/usePrevious';
 
 export interface ITaxonomyManagerProps {
   data: TaxonomyData | undefined;
@@ -27,6 +30,9 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
 }: React.PropsWithChildren<ITaxonomyManagerProps>) => {
   const settings = useRecoilValue(SettingsSelector);
   const { getColors } = useThemeColors();
+  const [filterValue, setFilterValue] = React.useState('');
+  const debounceFilterValue = useDebounce<string>(filterValue, 500);
+  const prevTaxonomy = usePrevious<string | null>(taxonomy);
 
   const onCreate = () => {
     Messenger.send(DashboardMessage.createTaxonomy, {
@@ -63,11 +69,15 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
         return 0;
       });
 
+      if (debounceFilterValue) {
+        crntItems = crntItems.filter((i) => i.toLowerCase().includes(debounceFilterValue.toLowerCase()));
+      }
+
       return crntItems.filter(i => i);
     }
 
     return [];
-  }, [data, taxonomy]);
+  }, [data, taxonomy, debounceFilterValue]);
 
   const unmappedItems = useMemo(() => {
     let unmapped: string[] = [];
@@ -108,8 +118,20 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
       }
     }
 
-    return [...new Set(unmapped)].filter(i => i);
-  }, [items, taxonomy, pages, settings?.contentTypes]);
+    const unmappedItems = [...new Set(unmapped)].filter(i => i);
+
+    if (debounceFilterValue) {
+      return unmappedItems.filter((i) => i.toLowerCase().includes(debounceFilterValue.toLowerCase()));
+    }
+
+    return unmappedItems;
+  }, [items, taxonomy, pages, settings?.contentTypes, debounceFilterValue]);
+
+  React.useEffect(() => {
+    if (prevTaxonomy !== taxonomy) {
+      setFilterValue('');
+    }
+  }, [prevTaxonomy, taxonomy])
 
   if (!taxonomy) {
     return null;
@@ -134,19 +156,27 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
             {l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerDescription, taxonomy)}
           </p>
         </div>
-        <div>
-          <button
-            className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium focus:outline-none rounded ${getColors(
-              `text-white dark:text-vulcan-500 bg-teal-600 hover:bg-teal-700 disabled:bg-gray-500`,
-              `text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`
-            )
-              }`}
-            title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}
-            onClick={onCreate}
-          >
-            <PlusSmIcon className={`mr-2 h-6 w-6`} />
-            <span className={`text-sm`}>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}</span>
-          </button>
+        <div className='flex gap-4 justify-center items-center'>
+          <FilterInput
+            placeholder='Filter'
+            value={filterValue}
+            onChange={(value) => setFilterValue(value)}
+            onReset={() => setFilterValue('')} />
+
+          <div>
+            <button
+              className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium focus:outline-none rounded ${getColors(
+                `text-white dark:text-vulcan-500 bg-teal-600 hover:bg-teal-700 disabled:bg-gray-500`,
+                `text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`
+              )
+                }`}
+              title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}
+              onClick={onCreate}
+            >
+              <PlusSmIcon className={`mr-2 h-6 w-6`} />
+              <span className={`text-sm`}>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}</span>
+            </button>
+          </div>
         </div>
       </div>
 
diff --git a/src/dashboardWebView/components/TaxonomyView/TaxonomyView.tsx b/src/dashboardWebView/components/TaxonomyView/TaxonomyView.tsx
index b37653a6..1ff758eb 100644
--- a/src/dashboardWebView/components/TaxonomyView/TaxonomyView.tsx
+++ b/src/dashboardWebView/components/TaxonomyView/TaxonomyView.tsx
@@ -2,12 +2,12 @@ import { Messenger } from '@estruyf/vscode/dist/client';
 import { ChevronRightIcon, DownloadIcon } from '@heroicons/react/outline';
 import * as React from 'react';
 import { useEffect, useState } from 'react';
-import { useRecoilValue } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
 import { TelemetryEvent } from '../../../constants';
 import { TaxonomyData } from '../../../models';
 import { DashboardMessage } from '../../DashboardMessage';
-import { Page } from '../../models';
-import { SettingsSelector } from '../../state';
+import { NavigationType, Page } from '../../models';
+import { DashboardViewAtom, SettingsSelector } from '../../state';
 import { NavigationBar, NavigationItem } from '../Layout';
 import { PageLayout } from '../Layout/PageLayout';
 import { SponsorMsg } from '../Layout/SponsorMsg';
@@ -25,6 +25,7 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
   const settings = useRecoilValue(SettingsSelector);
   const [taxonomySettings, setTaxonomySettings] = useState<TaxonomyData>();
   const [selectedTaxonomy, setSelectedTaxonomy] = useState<string | null>(`tags`);
+  const [, setView] = useRecoilState(DashboardViewAtom);
 
   const onImport = () => {
     Messenger.send(DashboardMessage.importTaxonomy);
@@ -39,6 +40,7 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
   }, [settings?.tags, settings?.categories, settings?.customTaxonomy]);
 
   useEffect(() => {
+    setView(NavigationType.Taxonomy);
     Messenger.send(DashboardMessage.sendTelemetry, {
       event: TelemetryEvent.webviewTaxonomyDashboard
     });
@@ -90,7 +92,10 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
         </NavigationBar>
 
         <div className={`w-10/12 h-full overflow-hidden`}>
-          <TaxonomyManager data={taxonomySettings} taxonomy={selectedTaxonomy} pages={pages} />
+          <TaxonomyManager
+            data={taxonomySettings}
+            taxonomy={selectedTaxonomy}
+            pages={pages} />
         </div>
       </div>
 
diff --git a/src/dashboardWebView/components/WelcomeView/WelcomeScreen.tsx b/src/dashboardWebView/components/WelcomeView/WelcomeScreen.tsx
index 50605d9c..1a20352e 100644
--- a/src/dashboardWebView/components/WelcomeView/WelcomeScreen.tsx
+++ b/src/dashboardWebView/components/WelcomeView/WelcomeScreen.tsx
@@ -1,16 +1,18 @@
-import { HeartIcon, StarIcon } from '@heroicons/react/outline';
+import { BookOpenIcon, HeartIcon, StarIcon } from '@heroicons/react/outline';
 import * as React from 'react';
-import { GITHUB_LINK, REVIEW_LINK, SPONSOR_LINK, TelemetryEvent } from '../../../constants';
+import { DOCUMENTATION_LINK, GITHUB_LINK, REVIEW_LINK, SPONSOR_LINK, TelemetryEvent } from '../../../constants';
 import { Messenger } from '@estruyf/vscode/dist/client';
 import { FrontMatterIcon } from '../../../panelWebView/components/Icons/FrontMatterIcon';
 import { GitHubIcon } from '../../../panelWebView/components/Icons/GitHubIcon';
 import { DashboardMessage } from '../../DashboardMessage';
 import { Settings } from '../../models/Settings';
 import { StepsToGetStarted } from '../Steps/StepsToGetStarted';
-import useThemeColors from '../../hooks/useThemeColors';
 import { WelcomeLink } from './WelcomeLink';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import { DashboardViewAtom } from '../../state';
+import { useRecoilState } from 'recoil';
+import { NavigationType } from '../../models';
 
 export interface IWelcomeScreenProps {
   settings: Settings;
@@ -19,9 +21,10 @@ export interface IWelcomeScreenProps {
 export const WelcomeScreen: React.FunctionComponent<IWelcomeScreenProps> = ({
   settings
 }: React.PropsWithChildren<IWelcomeScreenProps>) => {
-  const { getColors } = useThemeColors();
+  const [, setView] = useRecoilState(DashboardViewAtom);
 
   React.useEffect(() => {
+    setView(NavigationType.Welcome);
     Messenger.send(DashboardMessage.sendTelemetry, {
       event: TelemetryEvent.webviewWelcomeScreen
     });
@@ -48,19 +51,11 @@ export const WelcomeScreen: React.FunctionComponent<IWelcomeScreenProps> = ({
                   {l10n.t(LocalizationKey.dashboardWelcomeScreenTitle)}
                 </h1>
 
-                <p className={`mt-3 text-base  sm:mt-5 sm:text-xl lg:text-lg xl:text-xl ${getColors(
-                  'text-vulcan-300 dark:text-whisper-700',
-                  'text-[var(--vscode-editor-foreground)]'
-                )
-                  }`}>
+                <p className={`mt-3 text-base  sm:mt-5 sm:text-xl lg:text-lg xl:text-xl text-[var(--vscode-editor-foreground)]`}>
                   {l10n.t(LocalizationKey.dashboardWelcomeScreenThanks)}
                 </p>
 
-                <p className={`mt-3 text-base sm:mt-5 sm:text-xl lg:text-lg xl:text-xl ${getColors(
-                  'text-vulcan-300 dark:text-whisper-700',
-                  'text-[var(--vscode-editor-foreground)]'
-                )
-                  }`}>
+                <p className={`mt-3 text-base sm:mt-5 sm:text-xl lg:text-lg xl:text-xl text-[var(--vscode-editor-foreground)]`}>
                   {l10n.t(LocalizationKey.dashboardWelcomeScreenDescription)}
                 </p>
 
@@ -73,6 +68,13 @@ export const WelcomeScreen: React.FunctionComponent<IWelcomeScreenProps> = ({
                       </span>
                     </WelcomeLink>
 
+                    <WelcomeLink href={DOCUMENTATION_LINK} title={l10n.t(LocalizationKey.dashboardWelcomeScreenLinkDocumentationLabel)}>
+                      <BookOpenIcon className="w-8 h-8" />
+                      <span className={`text-lg ml-2`}>
+                        {l10n.t(LocalizationKey.dashboardWelcomeScreenLinkDocumentationLabel)}
+                      </span>
+                    </WelcomeLink>
+
                     <WelcomeLink href={SPONSOR_LINK} title={l10n.t(LocalizationKey.dashboardWelcomeScreenLinkSponsorTitle)}>
                       <HeartIcon className="w-8 h-8" />
                       <span className={`text-lg ml-2`}>
@@ -92,11 +94,7 @@ export const WelcomeScreen: React.FunctionComponent<IWelcomeScreenProps> = ({
             </div>
 
             <div className="col-span-4 flex justify-center items-center">
-              <FrontMatterIcon className={`h-64 w-64 ${getColors(
-                'text-vulcan-500 dark:text-whisper-500',
-                'text-[var(--vscode-editor-foreground)]'
-              )
-                }`} />
+              <FrontMatterIcon className={`h-64 w-64 text-[var(--vscode-button-background)]`} />
             </div>
           </div>
         </div>
@@ -110,11 +108,7 @@ export const WelcomeScreen: React.FunctionComponent<IWelcomeScreenProps> = ({
             <div className={`col-span-8`}>
               <StepsToGetStarted settings={settings} />
 
-              <p className={`mt-5 text-sm  ${getColors(
-                'text-vulcan-300 dark:text-whisper-700',
-                'text-[var(--vscode-editor-foreground)]'
-              )
-                }`}>
+              <p className={`mt-5 text-sm text-[var(--vscode-editor-foreground)]`}>
                 {l10n.t(LocalizationKey.dashboardWelcomeScreenActionsDescription)}
               </p>
             </div>
diff --git a/src/dashboardWebView/hooks/index.ts b/src/dashboardWebView/hooks/index.ts
index 9682e0fc..df5f5509 100644
--- a/src/dashboardWebView/hooks/index.ts
+++ b/src/dashboardWebView/hooks/index.ts
@@ -1,3 +1,4 @@
+export * from './useCard';
 export * from './useExtensibility';
 export * from './useMedia';
 export * from './useMessages';
diff --git a/src/dashboardWebView/hooks/useCard.tsx b/src/dashboardWebView/hooks/useCard.tsx
new file mode 100644
index 00000000..40aa979b
--- /dev/null
+++ b/src/dashboardWebView/hooks/useCard.tsx
@@ -0,0 +1,55 @@
+import { useMemo } from 'react';
+import { CardFields, Page } from '../models';
+import * as l10n from '@vscode/l10n';
+import { LocalizationKey } from '../../localization';
+
+export default function useCard(
+  pageData: Page,
+  cardFields: CardFields | undefined,
+) {
+
+  const escapedTitle = useMemo(() => {
+    let value = pageData.title;
+
+    if (cardFields?.title) {
+      if (cardFields.title === "description") {
+        value = pageData.description;
+      } else if (cardFields?.title !== "title") {
+        value = pageData[cardFields?.title] || pageData.title;
+      }
+    } else if (cardFields?.title === null) {
+      return null;
+    }
+
+    if (value && typeof value !== 'string') {
+      return l10n.t(LocalizationKey.dashboardContentsItemInvalidTitle);
+    }
+
+    return value;
+  }, [pageData.title, pageData.description, cardFields?.title, pageData]);
+
+  const escapedDescription = useMemo(() => {
+    let value = pageData.description;
+
+    if (cardFields?.description) {
+      if (cardFields.description === "title") {
+        value = pageData.title;
+      } else if (cardFields?.description !== "description") {
+        value = pageData[cardFields?.description] || pageData.description;
+      }
+    } else if (cardFields?.description === null) {
+      return null;
+    }
+
+    if (value && typeof value !== 'string') {
+      return l10n.t(LocalizationKey.dashboardContentsItemInvalidDescription);
+    }
+
+    return value;
+  }, [pageData.description, pageData.title, cardFields?.description, pageData]);
+
+  return {
+    escapedTitle,
+    escapedDescription
+  };
+}
\ No newline at end of file
diff --git a/src/dashboardWebView/hooks/useMedia.tsx b/src/dashboardWebView/hooks/useMedia.tsx
index d6400fd7..08737d43 100644
--- a/src/dashboardWebView/hooks/useMedia.tsx
+++ b/src/dashboardWebView/hooks/useMedia.tsx
@@ -17,6 +17,7 @@ import {
 } from '../state';
 import Fuse from 'fuse.js';
 import usePagination from './usePagination';
+import { usePrevious } from '../../panelWebView/hooks/usePrevious';
 
 const fuseOptions: Fuse.IFuseOptions<MediaInfo> = {
   keys: [
@@ -31,7 +32,8 @@ const fuseOptions: Fuse.IFuseOptions<MediaInfo> = {
 
 export default function useMedia() {
   const [media, setMedia] = useState<MediaInfo[]>([]);
-  const page = useRecoilValue(PageAtom);
+  // const page = useRecoilValue(PageAtom);
+  const [page, setPage] = useRecoilState(PageAtom);
   const [searchedMedia, setSearchedMedia] = useState<MediaInfo[]>([]);
   const [, setSelectedFolder] = useRecoilState(SelectedMediaFolderAtom);
   const [, setTotal] = useRecoilState(MediaTotalAtom);
@@ -40,9 +42,16 @@ export default function useMedia() {
   const [, setAllStaticFolders] = useRecoilState(AllStaticFoldersAtom);
   const [, setLoading] = useRecoilState(LoadingAtom);
   const search = useRecoilValue(SearchAtom);
+  const prevSearch = usePrevious<string>(search);
   const settings = useRecoilValue(SettingsAtom);
   const { pageSetNr } = usePagination(settings?.dashboardState.contents.pagination);
 
+  useEffect(() => {
+    if (prevSearch !== search) {
+      setPage(0);
+    }
+  }, [search, prevSearch]);
+
   const getMedia = useCallback(() => {
     return searchedMedia.slice(page * pageSetNr, (page + 1) * pageSetNr);
   }, [searchedMedia, page, pageSetNr]);
diff --git a/src/dashboardWebView/hooks/usePages.tsx b/src/dashboardWebView/hooks/usePages.tsx
index 863038d0..98f3dc6e 100644
--- a/src/dashboardWebView/hooks/usePages.tsx
+++ b/src/dashboardWebView/hooks/usePages.tsx
@@ -20,7 +20,6 @@ import { Messenger } from '@estruyf/vscode/dist/client';
 import { DashboardMessage } from '../DashboardMessage';
 import { EventData } from '@estruyf/vscode/dist/models';
 import { parseWinPath } from '../../helpers/parseWinPath';
-import { format } from 'date-fns';
 
 export default function usePages(pages: Page[]) {
   const [pageItems, setPageItems] = useRecoilState(AllPagesAtom);
@@ -45,18 +44,23 @@ export default function usePages(pages: Page[]) {
       let pagesToShow: Page[] = Object.assign([], searchedPages);
 
       // Framework specific actions
-      if (framework?.toLowerCase() === 'jekyll') {
+      if (framework?.toLowerCase() === 'jekyll' || framework?.toLowerCase() === 'hexo') {
         pagesToShow = pagesToShow.map((page) => {
-          // https://jekyllrb.com/docs/posts/#drafts
-          const filePath = parseWinPath(page.fmFilePath);
-          page.draft = filePath.indexOf(`/_drafts/`) > -1;
-
-          // Published field: https://jekyllrb.com/docs/front-matter/#predefined-global-variables
-          if (typeof page.published !== 'undefined') {
-            page.draft = !page.published;
+          try {
+            const crntPage = Object.assign({}, page);
+            // https://jekyllrb.com/docs/posts/#drafts
+            const filePath = parseWinPath(page.fmFilePath);
+            crntPage.draft = filePath.indexOf(`/_drafts/`) > -1;
+
+            // Published field: https://jekyllrb.com/docs/front-matter/#predefined-global-variables
+            if (typeof crntPage.published !== 'undefined') {
+              crntPage.draft = !crntPage.published;
+            }
+
+            return crntPage;
+          } catch (error) {
+            return page;
           }
-
-          return page;
         });
       }
 
@@ -146,25 +150,28 @@ export default function usePages(pages: Page[]) {
         // Draft field is a boolean field
         const draftFieldName = draftField?.name || 'draft';
 
-        const drafts = crntPages.filter(
-          (page) => page[draftFieldName] == true || page[draftFieldName] === 'true'
-        );
-        const published = crntPages.filter(
-          (page) =>
-            page[draftFieldName] == false ||
-            page[draftFieldName] === 'false' ||
-            typeof page[draftFieldName] === 'undefined'
-        );
-
-        draftTypes[Tab.Draft] = draftField?.invert ? published.length : drafts.length;
-        draftTypes[Tab.Published] = draftField?.invert ? drafts.length : published.length;
-
-        if (tab === Tab.Published) {
-          crntPages = draftField?.invert ? drafts : published;
-        } else if (tab === Tab.Draft) {
-          crntPages = draftField?.invert ? published : drafts;
-        } else {
-          crntPages = crntPages;
+        const usesDraft = crntPages.some(x => typeof x[draftFieldName] !== 'undefined');
+        if (usesDraft) {
+          const drafts = crntPages.filter(
+            (page) => page[draftFieldName] == true || page[draftFieldName] === 'true'
+          );
+          const published = crntPages.filter(
+            (page) =>
+              page[draftFieldName] == false ||
+              page[draftFieldName] === 'false' ||
+              typeof page[draftFieldName] === 'undefined'
+          );
+
+          draftTypes[Tab.Draft] = draftField?.invert ? published.length : drafts.length;
+          draftTypes[Tab.Published] = draftField?.invert ? drafts.length : published.length;
+
+          if (tab === Tab.Published) {
+            crntPages = draftField?.invert ? drafts : published;
+          } else if (tab === Tab.Draft) {
+            crntPages = draftField?.invert ? published : drafts;
+          } else {
+            crntPages = crntPages;
+          }
         }
       }
 
diff --git a/src/dashboardWebView/index.tsx b/src/dashboardWebView/index.tsx
index 28e57ef2..e88753f2 100644
--- a/src/dashboardWebView/index.tsx
+++ b/src/dashboardWebView/index.tsx
@@ -45,7 +45,8 @@ export const routePaths: { [name: string]: string } = {
   media: '/media',
   snippets: '/snippets',
   data: '/data',
-  taxonomy: '/taxonomy'
+  taxonomy: '/taxonomy',
+  settings: '/settings',
 };
 
 const preserveColor = (color: string | undefined) => {
diff --git a/src/dashboardWebView/models/NavigationType.ts b/src/dashboardWebView/models/NavigationType.ts
index 862647d9..228ff12e 100644
--- a/src/dashboardWebView/models/NavigationType.ts
+++ b/src/dashboardWebView/models/NavigationType.ts
@@ -1,7 +1,9 @@
 export enum NavigationType {
+  Welcome = 'welcome',
   Contents = 'contents',
   Media = 'media',
   Data = 'data',
   Snippets = 'snippets',
-  Taxonomy = 'taxonomy'
+  Taxonomy = 'taxonomy',
+  Settings = 'settings'
 }
diff --git a/src/dashboardWebView/models/Page.ts b/src/dashboardWebView/models/Page.ts
index 2f3aefd4..2d20f3e0 100644
--- a/src/dashboardWebView/models/Page.ts
+++ b/src/dashboardWebView/models/Page.ts
@@ -6,6 +6,7 @@ export interface Page {
   // Front matter fields
   fmFolder: string;
   fmFilePath: string;
+  fmRelFileWsPath: string;
   fmRelFilePath: string;
   fmFileName: string;
   fmModified: number;
diff --git a/src/dashboardWebView/models/Settings.ts b/src/dashboardWebView/models/Settings.ts
index 0f320568..f5ff7b8d 100644
--- a/src/dashboardWebView/models/Settings.ts
+++ b/src/dashboardWebView/models/Settings.ts
@@ -45,6 +45,7 @@ export interface Settings {
   snippets: Snippets | undefined;
   snippetsWrapper: boolean;
   date: { format: string };
+  lastUpdated: number;
 }
 
 export interface DashboardState {
diff --git a/src/dashboardWebView/models/Status.ts b/src/dashboardWebView/models/Status.ts
index fde398ad..be23d857 100644
--- a/src/dashboardWebView/models/Status.ts
+++ b/src/dashboardWebView/models/Status.ts
@@ -1,5 +1,6 @@
 export enum Status {
   Active = 1,
   Completed,
-  NotStarted
+  NotStarted,
+  Optional
 }
diff --git a/src/dashboardWebView/state/atom/PinnedItems.ts b/src/dashboardWebView/state/atom/PinnedItems.ts
new file mode 100644
index 00000000..00d4cca3
--- /dev/null
+++ b/src/dashboardWebView/state/atom/PinnedItems.ts
@@ -0,0 +1,6 @@
+import { atom } from 'recoil';
+
+export const PinnedItemsAtom = atom<string[]>({
+  key: 'PinnedItemsAtom',
+  default: []
+});
diff --git a/src/extension.ts b/src/extension.ts
index 62aded6f..f13e8966 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -397,8 +397,12 @@ const handleAutoDateUpdate = (e: vscode.TextDocumentWillSaveEvent) => {
 };
 
 const triggerPageUpdate = (location: string) => {
-  Logger.info(`Triggering draft status update: ${location}`);
+  Logger.info(`Trigger page update: ${location}`);
   pageUpdateDebouncer(() => {
     StatusListener.verify(collection);
   }, 1000);
+
+  if (location === 'onDidChangeActiveTextEditor') {
+    PanelProvider.getInstance()?.updateCurrentFile();
+  }
 };
diff --git a/src/helpers/ArticleHelper.ts b/src/helpers/ArticleHelper.ts
index 30264981..bd7b5075 100644
--- a/src/helpers/ArticleHelper.ts
+++ b/src/helpers/ArticleHelper.ts
@@ -23,14 +23,14 @@ import {
 } from '../constants';
 import { DumpOptions } from 'js-yaml';
 import { FrontMatterParser, ParsedFrontMatter } from '../parsers';
-import { Extension, Logger, Settings, SlugHelper, parseWinPath } from '.';
+import { ContentType, Extension, Logger, Settings, SlugHelper, isValidFile, parseWinPath } from '.';
 import { format, parse } from 'date-fns';
 import { Notifications } from './Notifications';
 import { Article } from '../commands';
 import { join } from 'path';
 import { EditorHelper } from '@estruyf/vscode';
 import sanitize from '../helpers/Sanitize';
-import { ContentType } from '../models';
+import { ContentType as IContentType } from '../models';
 import { DateHelper } from './DateHelper';
 import { DiagnosticSeverity, Position, window, Range } from 'vscode';
 import { DEFAULT_FILE_TYPES } from '../constants/DefaultFileTypes';
@@ -305,14 +305,14 @@ export class ArticleHelper {
    * @returns
    */
   public static getContentTypes() {
-    return Settings.get<ContentType[]>(SETTING_TAXONOMY_CONTENT_TYPES) || [DEFAULT_CONTENT_TYPE];
+    return Settings.get<IContentType[]>(SETTING_TAXONOMY_CONTENT_TYPES) || [DEFAULT_CONTENT_TYPE];
   }
 
   /**
    * Retrieve the content type of the current file
    * @param updatedMetadata
    */
-  public static getContentType(metadata: { [field: string]: string }): ContentType {
+  public static getContentType(metadata: { [field: string]: string }): IContentType {
     const contentTypes = ArticleHelper.getContentTypes();
 
     if (!contentTypes || !metadata) {
@@ -331,6 +331,8 @@ export class ArticleHelper {
         contentType.fields = DEFAULT_CONTENT_TYPE.fields;
       }
 
+      contentType.fields = ContentType.mergeFields(contentType.fields);
+
       return contentType;
     }
 
@@ -372,7 +374,7 @@ export class ArticleHelper {
    * @returns The new file path
    */
   public static async createContent(
-    contentType: ContentType | undefined,
+    contentType: IContentType | undefined,
     folderPath: string,
     titleValue: string,
     fileExtension?: string
@@ -438,7 +440,7 @@ export class ArticleHelper {
   public static getFilePrefix(
     prefix: string | null | undefined,
     filePath?: string,
-    contentType?: ContentType
+    contentType?: IContentType
   ): string | undefined {
     if (!prefix) {
       prefix = undefined;
@@ -636,6 +638,22 @@ export class ArticleHelper {
     return null;
   }
 
+  /**
+   * Retrieve the active file
+   * @returns
+   */
+  public static getActiveFile() {
+    const editors = window.visibleTextEditors;
+    if (editors.length === 1) {
+      const editor = editors[0];
+      const filePath = parseWinPath(editor.document.uri.fsPath);
+      if (isValidFile(filePath)) {
+        return filePath;
+      }
+    }
+    return undefined;
+  }
+
   /**
    * Retrieve all the elements from the markdown content
    * @param node
diff --git a/src/helpers/ContentType.ts b/src/helpers/ContentType.ts
index 743ce51a..504f2cef 100644
--- a/src/helpers/ContentType.ts
+++ b/src/helpers/ContentType.ts
@@ -85,7 +85,7 @@ export class ContentType {
     }
 
     const contentTypes = ContentType.getAll();
-    const folders = Folders.get();
+    const folders = Folders.get().filter((f) => !f.disableCreation);
     const folder = folders.find((f) => f.title === selectedFolder);
 
     if (!folder) {
@@ -111,7 +111,50 @@ export class ContentType {
    * @returns
    */
   public static getAll() {
-    return Settings.get<IContentType[]>(SETTING_TAXONOMY_CONTENT_TYPES);
+    const cts = Settings.get<IContentType[]>(SETTING_TAXONOMY_CONTENT_TYPES);
+
+    for (const ct of cts || []) {
+      ct.fields = ContentType.mergeFields(ct.fields || []);
+    }
+
+    return cts;
+  }
+
+  /**
+   * Merge the collection fields
+   * @param contentType
+   * @returns
+   */
+  public static mergeFields(fields: Field[]) {
+    if (!fields) {
+      return [];
+    }
+
+    // Check if there is a field collection
+    const fcFields = ContentType.findAllFieldsByType(fields || [], 'fieldCollection');
+    if (fcFields.length > 0) {
+      const fieldGroups = Settings.get<FieldGroup[]>(SETTING_TAXONOMY_FIELD_GROUPS);
+
+      if (fieldGroups && fieldGroups.length > 0) {
+        for (const cField of fcFields) {
+          for (const fieldName of cField) {
+            const field = fields.find((f) => f.name === fieldName);
+
+            if (field && field.type === 'fieldCollection') {
+              const fieldGroup = fieldGroups.find((fg) => fg.id === field.fieldGroup);
+              if (fieldGroup) {
+                const fieldIdx = fields.findIndex((f) => f.name === field.name);
+                fields.splice(fieldIdx, 1, ...fieldGroup.fields);
+              }
+            } else if (field && field.type === 'fields') {
+              fields = field.fields || [];
+            }
+          }
+        }
+      }
+    }
+
+    return fields;
   }
 
   /**
@@ -211,7 +254,7 @@ export class ContentType {
 
     await Settings.update(SETTING_TAXONOMY_CONTENT_TYPES, contentTypes, true);
 
-    const configPath = Settings.projectConfigPath;
+    const configPath = await Settings.projectConfigPath();
     const notificationAction = await Notifications.info(
       `Content type ${contentTypeName} has been ${overrideBool ? `updated` : `generated`}.`,
       configPath && (await existsAsync(configPath)) ? `Open settings` : undefined
@@ -248,7 +291,7 @@ export class ContentType {
 
     await Settings.update(SETTING_TAXONOMY_CONTENT_TYPES, contentTypes, true);
 
-    const configPath = Settings.projectConfigPath;
+    const configPath = await Settings.projectConfigPath();
     const notificationAction = await Notifications.info(
       `Content type ${contentType.name} has been updated.`,
       configPath && (await existsAsync(configPath)) ? `Open settings` : undefined
@@ -395,6 +438,29 @@ export class ContentType {
     return parents;
   }
 
+  /**
+   * Find all the fields by type
+   * @param fields
+   * @param type
+   * @returns
+   */
+  public static findAllFieldsByType(fields: Field[], type: FieldType): string[][] {
+    let parents: string[][] = [];
+
+    for (const field of fields) {
+      if (field.type === type) {
+        parents.push([field.name]);
+      } else if (field.type === 'fields' && field.fields) {
+        const subFields = this.findAllFieldsByType(field.fields, type);
+        if (subFields.length > 0) {
+          parents = [...parents, ...subFields.map((f) => [field.name, ...f])];
+        }
+      }
+    }
+
+    return parents;
+  }
+
   /**
    * Find the preview field in the fields
    * @param ctFields
diff --git a/src/helpers/DashboardSettings.ts b/src/helpers/DashboardSettings.ts
index 6d1aaf6d..64e1d617 100644
--- a/src/helpers/DashboardSettings.ts
+++ b/src/helpers/DashboardSettings.ts
@@ -46,6 +46,7 @@ import { FrameworkDetector } from './FrameworkDetector';
 import { Settings } from './SettingsHelper';
 import { parseWinPath } from './parseWinPath';
 import { TaxonomyHelper } from './TaxonomyHelper';
+import { ContentType } from './ContentType';
 
 export class DashboardSettings {
   private static cachedSettings: ISettings | undefined = undefined;
@@ -61,7 +62,7 @@ export class DashboardSettings {
   public static async getSettings() {
     const ext = Extension.getInstance();
     const wsFolder = Folders.getWorkspaceFolder();
-    const isInitialized = Project.isInitialized();
+    const isInitialized = await Project.isInitialized();
     const gitActions = Settings.get<boolean>(SETTING_GIT_ENABLED);
     const pagination = Settings.get<boolean | number>(SETTING_DASHBOARD_CONTENT_PAGINATION);
 
@@ -85,7 +86,7 @@ export class DashboardSettings {
         ExtensionState.PagesView,
         'workspace'
       ),
-      contentTypes: Settings.get(SETTING_TAXONOMY_CONTENT_TYPES) || [],
+      contentTypes: ContentType.getAll() || [],
       draftField: Settings.get<DraftField>(SETTING_CONTENT_DRAFT_FIELD),
       customSorting: Settings.get<SortingSetting[]>(SETTING_CONTENT_SORTING),
       contentFolders: Folders.get(),
@@ -133,7 +134,8 @@ export class DashboardSettings {
       snippets: Settings.get<Snippets>(SETTING_CONTENT_SNIPPETS),
       snippetsWrapper: Settings.get<boolean>(SETTING_SNIPPETS_WRAPPER),
       isBacker: await ext.getState<boolean | undefined>(CONTEXT.backer, 'global'),
-      websiteUrl: Settings.get<string>(SETTING_WEBSITE_URL)
+      websiteUrl: Settings.get<string>(SETTING_WEBSITE_URL),
+      lastUpdated: new Date().getTime()
     } as ISettings;
 
     return settings;
diff --git a/src/helpers/FilesHelper.ts b/src/helpers/FilesHelper.ts
index 2f1815e8..840a32de 100644
--- a/src/helpers/FilesHelper.ts
+++ b/src/helpers/FilesHelper.ts
@@ -1,7 +1,9 @@
 import { Notifications } from './Notifications';
-import { Uri, workspace } from 'vscode';
-import { Folders } from '../commands/Folders';
+import { Uri } from 'vscode';
+import { Folders, WORKSPACE_PLACEHOLDER } from '../commands/Folders';
 import { isValidFile } from './isValidFile';
+import { parseWinPath } from './parseWinPath';
+import { join } from 'path';
 
 export class FilesHelper {
   /**
@@ -28,4 +30,26 @@ export class FilesHelper {
 
     return pages;
   }
+
+  /**
+   * Relative path to absolute path
+   * @param filePath
+   * @returns
+   */
+  public static relToAbsPath(filePath: string): string {
+    const wsFolder = Folders.getWorkspaceFolder();
+    let absPath = join(parseWinPath(wsFolder?.fsPath || ''), filePath);
+    return parseWinPath(absPath);
+  }
+
+  /**
+   * Absolute path to rel path
+   * @param filePath
+   * @returns
+   */
+  public static absToRelPath(filePath: string): string {
+    const wsFolder = Folders.getWorkspaceFolder();
+    const relPath = filePath.replace(wsFolder?.fsPath || '', WORKSPACE_PLACEHOLDER);
+    return parseWinPath(relPath);
+  }
 }
diff --git a/src/helpers/FrameworkDetector.ts b/src/helpers/FrameworkDetector.ts
index 1e7ab105..43ace018 100644
--- a/src/helpers/FrameworkDetector.ts
+++ b/src/helpers/FrameworkDetector.ts
@@ -163,7 +163,7 @@ export class FrameworkDetector {
       if (await existsAsync(hexoConfig)) {
         const content = await readFileAsync(hexoConfig, 'utf8');
         // Convert YAML to JSON
-        const config = jsyaml.safeLoad(content);
+        const config = jsyaml.load(content);
 
         // Check if post assets are used: https://hexo.io/docs/asset-folders.html#Post-Asset-Folder
         if (config.post_asset_folder) {
@@ -171,6 +171,25 @@ export class FrameworkDetector {
         }
       }
 
+      const draftsPath = join(wsFolder?.fsPath || '', 'source', '_drafts');
+      const postsPath = join(wsFolder?.fsPath || '', 'source', '_posts');
+
+      if (await existsAsync(draftsPath)) {
+        const folderUri = Uri.file(draftsPath);
+        await commands.executeCommand(COMMAND_NAME.registerFolder, {
+          title: 'drafts',
+          path: folderUri
+        });
+      }
+
+      if (await existsAsync(postsPath)) {
+        const folderUri = Uri.file(postsPath);
+        await commands.executeCommand(COMMAND_NAME.registerFolder, {
+          title: 'posts',
+          path: folderUri
+        });
+      }
+
       await Settings.update(SETTING_CONTENT_STATIC_FOLDER, assetFoler, true);
     } catch (e) {
       Logger.error(
@@ -191,7 +210,7 @@ export class FrameworkDetector {
       if (await existsAsync(jekyllConfig)) {
         const content = await readFileAsync(jekyllConfig, 'utf8');
         // Convert YAML to JSON
-        const config = jsyaml.safeLoad(content);
+        const config = jsyaml.load(content);
 
         if (config.collections_dir) {
           collectionDir = config.collections_dir;
@@ -203,7 +222,7 @@ export class FrameworkDetector {
 
       if (await existsAsync(draftsPath)) {
         const folderUri = Uri.file(draftsPath);
-        commands.executeCommand(COMMAND_NAME.registerFolder, {
+        await commands.executeCommand(COMMAND_NAME.registerFolder, {
           title: 'drafts',
           path: folderUri
         });
@@ -211,7 +230,7 @@ export class FrameworkDetector {
 
       if (await existsAsync(postsPath)) {
         const folderUri = Uri.file(postsPath);
-        commands.executeCommand(COMMAND_NAME.registerFolder, {
+        await commands.executeCommand(COMMAND_NAME.registerFolder, {
           title: 'posts',
           path: folderUri
         });
diff --git a/src/helpers/ImageHelper.ts b/src/helpers/ImageHelper.ts
index a8091801..3c20de29 100644
--- a/src/helpers/ImageHelper.ts
+++ b/src/helpers/ImageHelper.ts
@@ -7,6 +7,7 @@ import { existsSync } from 'fs';
 import { Folders } from '../commands/Folders';
 import { parseWinPath } from './parseWinPath';
 import { Preview } from '../commands';
+import { ArticleHelper } from './ArticleHelper';
 
 export class ImageHelper {
   /**
@@ -16,7 +17,10 @@ export class ImageHelper {
    * @returns
    */
   public static allRelToAbs(field: Field, value: string | string[] | undefined) {
-    const filePath = window.activeTextEditor?.document.uri.fsPath || Preview.filePath;
+    let filePath =
+      window.activeTextEditor?.document.uri.fsPath ||
+      Preview.filePath ||
+      ArticleHelper.getActiveFile();
     if (!filePath) {
       return;
     }
@@ -27,7 +31,7 @@ export class ImageHelper {
       if (Array.isArray(value)) {
         previewUri = value.map((v) => ({
           original: v,
-          absPath: v.startsWith('http') ? v : ImageHelper.relToAbs(filePath, v)
+          absPath: v.startsWith('http') ? v : ImageHelper.relToAbs(filePath as string, v)
         }));
       }
     } else {
diff --git a/src/helpers/MediaHelpers.ts b/src/helpers/MediaHelpers.ts
index 6548dbf5..427f3752 100644
--- a/src/helpers/MediaHelpers.ts
+++ b/src/helpers/MediaHelpers.ts
@@ -26,6 +26,7 @@ import imageSize from 'image-size';
 import { EditorHelper } from '@estruyf/vscode';
 import { SortOption } from '../dashboardWebView/constants/SortOption';
 import { DataListener, MediaListener } from '../listeners/panel';
+import { MediaListener as DashboardMediaListener } from '../listeners/dashboard';
 import { ArticleHelper } from './ArticleHelper';
 import { lookup } from 'mime-types';
 import { existsAsync, readdirAsync, unlinkAsync, writeFileAsync } from '../utils';
@@ -273,6 +274,10 @@ export class MediaHelpers {
    */
   public static resetMedia() {
     MediaHelpers.media = [];
+
+    if (Dashboard.isOpen) {
+      DashboardMediaListener.sendMediaFiles();
+    }
   }
 
   /**
@@ -345,6 +350,8 @@ export class MediaHelpers {
     try {
       await unlinkAsync(file);
 
+      MediaLibrary.getInstance().remove(file);
+
       MediaHelpers.media = [];
       return true;
     } catch (err: any) {
diff --git a/src/helpers/MediaLibrary.ts b/src/helpers/MediaLibrary.ts
index 663984c2..60b70bcf 100644
--- a/src/helpers/MediaLibrary.ts
+++ b/src/helpers/MediaLibrary.ts
@@ -1,5 +1,5 @@
 import { MediaHelpers } from './MediaHelpers';
-import { workspace } from 'vscode';
+import { Disposable, workspace } from 'vscode';
 import { Config, JsonDB } from 'node-json-db';
 import { basename, dirname, join, parse } from 'path';
 import { Folders, WORKSPACE_PLACEHOLDER } from '../commands/Folders';
@@ -8,6 +8,7 @@ import { parseWinPath } from './parseWinPath';
 import { LocalStore } from '../constants';
 import { existsAsync, renameAsync } from '../utils';
 import { existsSync, mkdirSync, renameSync } from 'fs';
+import { lookup } from 'mime-types';
 
 interface MediaRecord {
   description: string;
@@ -16,6 +17,8 @@ interface MediaRecord {
 
 export class MediaLibrary {
   private db: JsonDB | undefined;
+  private renameFilesListener: Disposable | undefined;
+  private removeFilesListener: Disposable | undefined;
   private static instance: MediaLibrary;
 
   private constructor() {
@@ -65,17 +68,29 @@ export class MediaLibrary {
       )
     );
 
-    workspace.onDidRenameFiles((e) => {
-      e.files.forEach((f) => {
+    if (this.renameFilesListener) {
+      this.renameFilesListener.dispose();
+    }
+
+    this.renameFilesListener = workspace.onDidRenameFiles((e) => {
+      e.files.forEach(async (f) => {
         const path = f.oldUri.path.toLowerCase();
-        // Check if file is an image
-        if (
-          path.endsWith('.jpeg') ||
-          path.endsWith('.jpg') ||
-          path.endsWith('.png') ||
-          path.endsWith('.gif')
-        ) {
-          this.rename(f.oldUri.fsPath, f.newUri.fsPath);
+        if (MediaLibrary.isMediaFile(path)) {
+          await this.rename(f.oldUri.fsPath, f.newUri.fsPath);
+          MediaHelpers.resetMedia();
+        }
+      });
+    });
+
+    if (this.removeFilesListener) {
+      this.removeFilesListener.dispose();
+    }
+
+    this.removeFilesListener = workspace.onDidDeleteFiles((e) => {
+      e.files.forEach(async (f) => {
+        const path = f.path.toLowerCase();
+        if (MediaLibrary.isMediaFile(path)) {
+          this.remove(f.fsPath);
           MediaHelpers.resetMedia();
         }
       });
@@ -90,6 +105,10 @@ export class MediaLibrary {
     return MediaLibrary.instance;
   }
 
+  public static reset() {
+    MediaLibrary.instance = new MediaLibrary();
+  }
+
   public async get(id: string): Promise<MediaRecord | undefined> {
     try {
       const fileId = this.parsePath(id);
@@ -102,21 +121,35 @@ export class MediaLibrary {
     }
   }
 
+  public async getAll() {
+    try {
+      const data = await this.db?.getData('/');
+      return data;
+    } catch {
+      return undefined;
+    }
+  }
+
   public set(id: string, metadata: any): void {
     const fileId = this.parsePath(id);
     this.db?.push(fileId, metadata, true);
   }
 
-  public rename(oldId: string, newId: string): void {
+  public async rename(oldId: string, newId: string): Promise<void> {
     const fileId = this.parsePath(oldId);
     const newFileId = this.parsePath(newId);
-    const data = this.db?.getData(fileId);
+    const data = await this.get(fileId);
     if (data) {
       this.db?.delete(fileId);
       this.db?.push(newFileId, data, true);
     }
   }
 
+  public async remove(path: string): Promise<void> {
+    const fileId = this.parsePath(path);
+    await this.db?.delete(fileId);
+  }
+
   public async updateFilename(filePath: string, filename: string) {
     const name = basename(filePath);
 
@@ -130,7 +163,7 @@ export class MediaLibrary {
           Notifications.warning(`The name "${filename}" already exists at the file location.`);
         } else {
           await renameAsync(filePath, newPath);
-          this.rename(filePath, newPath);
+          await this.rename(filePath, newPath);
           MediaHelpers.resetMedia();
         }
       } catch (err) {
@@ -139,11 +172,26 @@ export class MediaLibrary {
     }
   }
 
-  private parsePath(path: string) {
+  public parsePath(path: string) {
     const wsFolder = Folders.getWorkspaceFolder();
     const isWindows = process.platform === 'win32';
     let absPath = path.replace(parseWinPath(wsFolder?.fsPath || ''), WORKSPACE_PLACEHOLDER);
     absPath = isWindows ? absPath.split('\\').join('/') : absPath;
     return absPath.toLowerCase();
   }
+
+  private static isMediaFile(path: string) {
+    const mimeType = lookup(path);
+    // Check if file is an image
+    if (
+      mimeType &&
+      (mimeType.startsWith('image/') ||
+        mimeType.startsWith('video/') ||
+        mimeType.startsWith('audio/') ||
+        mimeType.startsWith('application/pdf'))
+    ) {
+      return true;
+    }
+    return false;
+  }
 }
diff --git a/src/helpers/PanelSettings.ts b/src/helpers/PanelSettings.ts
index f60c634f..160d7d9c 100644
--- a/src/helpers/PanelSettings.ts
+++ b/src/helpers/PanelSettings.ts
@@ -1,6 +1,10 @@
-import { SETTING_SPONSORS_AI_ENABLED, SETTING_WEBSITE_URL } from './../constants/settings';
+import {
+  SETTING_PANEL_ACTIONS_DISABLED,
+  SETTING_SPONSORS_AI_ENABLED,
+  SETTING_WEBSITE_URL
+} from './../constants/settings';
 import { workspace } from 'vscode';
-import { Extension, Settings, TaxonomyHelper } from '.';
+import { ContentType, Extension, Settings, TaxonomyHelper } from '.';
 import { Dashboard } from '../commands/Dashboard';
 import { Preview } from '../commands/Preview';
 import { Project } from '../commands/Project';
@@ -38,6 +42,7 @@ import {
   DraftField,
   FieldGroup,
   PanelSettings as IPanelSettings,
+  PanelAction,
   ScriptType,
   TaxonomyType
 } from '../models';
@@ -77,13 +82,13 @@ export class PanelSettings {
       scripts: (Settings.get<CustomScript[]>(SETTING_CUSTOM_SCRIPTS) || []).filter(
         (s) => (s.type === ScriptType.Content || !s.type) && !s.hidden
       ),
-      isInitialized: Project.isInitialized(),
+      isInitialized: await Project.isInitialized(),
       modifiedDateUpdate: Settings.get(SETTING_AUTO_UPDATE_DATE) || false,
       writingSettingsEnabled: this.isWritingSettingsEnabled() || false,
       fmHighlighting: Settings.get(SETTING_CONTENT_FRONTMATTER_HIGHLIGHT),
       preview: Preview.getSettings(),
       commaSeparatedFields: Settings.get(SETTING_COMMA_SEPARATED_FIELDS) || [],
-      contentTypes: Settings.get(SETTING_TAXONOMY_CONTENT_TYPES) || [],
+      contentTypes: ContentType.getAll() || [],
       dashboardViewData: Dashboard.viewData,
       draftField: Settings.get<DraftField>(SETTING_CONTENT_DRAFT_FIELD),
       isBacker: await Extension.getInstance().getState<boolean | undefined>(
@@ -97,7 +102,8 @@ export class PanelSettings {
       dataTypes: Settings.get<DataType[]>(SETTING_DATA_TYPES),
       fieldGroups: Settings.get<FieldGroup[]>(SETTING_TAXONOMY_FIELD_GROUPS),
       contentFolders: Folders.get(),
-      websiteUrl: Settings.get<string>(SETTING_WEBSITE_URL) || ''
+      websiteUrl: Settings.get<string>(SETTING_WEBSITE_URL) || '',
+      disabledActions: Settings.get<PanelAction[]>(SETTING_PANEL_ACTIONS_DISABLED) || []
     };
   }
 
diff --git a/src/helpers/Questions.ts b/src/helpers/Questions.ts
index e4806696..2bd347d6 100644
--- a/src/helpers/Questions.ts
+++ b/src/helpers/Questions.ts
@@ -116,7 +116,7 @@ export class Questions {
   public static async SelectContentFolder(
     showWarning: boolean = true
   ): Promise<string | undefined> {
-    let folders = Folders.get();
+    let folders = Folders.get().filter((f) => !f.disableCreation);
 
     let selectedFolder: string | undefined;
     if (folders.length > 1) {
diff --git a/src/helpers/SettingsHelper.ts b/src/helpers/SettingsHelper.ts
index b567a3fd..04467855 100644
--- a/src/helpers/SettingsHelper.ts
+++ b/src/helpers/SettingsHelper.ts
@@ -1,4 +1,8 @@
-import { SETTING_PROJECTS } from './../constants/settings';
+import {
+  EXTENSION_NAME,
+  SETTING_CONFIG_DYNAMIC_FILE_PATH,
+  SETTING_PROJECTS
+} from './../constants/settings';
 import { parseWinPath } from './parseWinPath';
 import { Telemetry } from './Telemetry';
 import { Notifications } from './Notifications';
@@ -51,6 +55,7 @@ import { ModeSwitch } from '../services/ModeSwitch';
 export class Settings {
   public static globalFile = 'frontmatter.json';
   public static globalConfigFolder = '.frontmatter/config';
+  public static globalConfigPath: string | undefined = undefined;
   public static globalConfig: any;
   private static config: vscode.WorkspaceConfiguration;
   private static isInitialized: boolean = false;
@@ -99,7 +104,7 @@ export class Settings {
     }
 
     if (!allCommands.includes(COMMAND_NAME.settingsRefresh)) {
-      commands.registerCommand(COMMAND_NAME.settingsRefresh, Settings.reloadConfig);
+      commands.registerCommand(COMMAND_NAME.settingsRefresh, Settings.refreshConfig);
     }
 
     Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
@@ -226,14 +231,14 @@ export class Settings {
    * Check for config changes on global and local settings
    * @param callback
    */
-  public static onConfigChange() {
-    const projectConfig = Settings.projectConfigPath;
+  public static async onConfigChange() {
+    const projectConfig = await Settings.projectConfigPath();
 
     workspace.onDidChangeConfiguration(() => {
       Settings.triggerListeners();
     });
 
-    if (projectConfig && !existsSync(projectConfig)) {
+    if (projectConfig && !(await existsAsync(projectConfig))) {
       // No config file, no need to watch
       Settings.createFileCreationWatcher();
       return;
@@ -264,7 +269,7 @@ export class Settings {
     Settings.fileSaveListener = workspace.onDidSaveTextDocument(async (e) => {
       const filename = e.uri.fsPath;
 
-      if (Settings.checkProjectConfig(filename)) {
+      if (await Settings.checkProjectConfig(filename)) {
         Logger.info(`Config change detected - ${filename} saved`);
         await Settings.reloadConfig();
       }
@@ -275,7 +280,7 @@ export class Settings {
     }
 
     Settings.fileDeleteListener = workspace.onDidDeleteFiles(async (e) => {
-      const needCallback = e?.files.find((f) => Settings.checkProjectConfig(f.fsPath));
+      const needCallback = e?.files.find(async (f) => await Settings.checkProjectConfig(f.fsPath));
       if (needCallback) {
         await Settings.reloadConfig(false);
       }
@@ -350,7 +355,7 @@ export class Settings {
    * @param value
    */
   public static async update<T>(name: string, value: T, updateGlobal: boolean = false) {
-    const fmConfig = Settings.projectConfigPath;
+    const fmConfig = await Settings.projectConfigPath();
 
     if (updateGlobal) {
       if (fmConfig && (await existsAsync(fmConfig))) {
@@ -381,7 +386,7 @@ export class Settings {
   }
 
   public static async remove(name: string) {
-    const fmConfig = Settings.projectConfigPath;
+    const fmConfig = await Settings.projectConfigPath();
 
     if (fmConfig && (await existsAsync(fmConfig))) {
       const localConfig = await readFileAsync(fmConfig, 'utf8');
@@ -408,10 +413,18 @@ export class Settings {
   /**
    * Checks if the project contains the frontmatter.json file
    */
-  public static hasProjectFile() {
+  public static async hasProjectFile(): Promise<boolean> {
     const wsFolder = Folders.getWorkspaceFolder();
-    const configPath = join(wsFolder?.fsPath || '', Settings.globalFile);
-    return existsSync(configPath);
+    if (!wsFolder) {
+      return false;
+    }
+
+    const globalConfigPath = await Settings.projectConfigPath();
+    if (!globalConfigPath) {
+      return false;
+    }
+
+    return await existsAsync(globalConfigPath);
   }
 
   /**
@@ -561,13 +574,30 @@ export class Settings {
    * Get the project config path
    * @returns
    */
-  public static get projectConfigPath() {
-    const wsFolder = Folders.getWorkspaceFolder();
-    if (wsFolder) {
-      const fmConfig = join(wsFolder.fsPath, Settings.globalFile);
-      return fmConfig;
+  public static async projectConfigPath() {
+    if (Settings.globalConfigPath) {
+      return Settings.globalConfigPath;
     }
-    return undefined;
+
+    const rootFilePath = join(Folders.getWorkspaceFolder()?.fsPath || '', Settings.globalFile);
+    if (await existsAsync(rootFilePath)) {
+      Settings.globalConfigPath = rootFilePath;
+      return Settings.globalConfigPath;
+    }
+
+    let configFiles = await workspace.findFiles(`**/${Settings.globalFile}`);
+    // Sort by file path length
+    configFiles = configFiles.sort((a, b) => a.fsPath.localeCompare(b.fsPath));
+
+    if (configFiles.length === 0) {
+      Settings.globalConfigPath = undefined;
+      return Settings.globalConfigPath;
+    }
+
+    const configPath = configFiles[0].fsPath;
+    Settings.globalConfigPath = configPath;
+
+    return Settings.globalConfigPath;
   }
 
   /**
@@ -575,8 +605,8 @@ export class Settings {
    * @param filePath
    * @returns
    */
-  private static checkProjectConfig(filePath: string) {
-    const fmConfig = Settings.projectConfigPath;
+  private static async checkProjectConfig(filePath: string) {
+    const fmConfig = await Settings.projectConfigPath();
     filePath = parseWinPath(filePath);
 
     if (filePath.includes(Settings.globalConfigFolder)) {
@@ -597,7 +627,7 @@ export class Settings {
    */
   private static async readConfig() {
     try {
-      const fmConfig = Settings.projectConfigPath;
+      const fmConfig = await Settings.projectConfigPath();
       if (fmConfig && (await existsAsync(fmConfig))) {
         const localConfig = await readFileAsync(fmConfig, 'utf8');
         Settings.globalConfig = jsoncParser.parse(localConfig);
@@ -620,6 +650,45 @@ export class Settings {
       for await (const configFile of configFiles) {
         await Settings.processConfigFile(configFile);
       }
+
+      // Check if there is a dynamic config file and use it to update the global config
+      if (
+        Settings.globalConfig &&
+        Settings.globalConfig[`${CONFIG_KEY}.${SETTING_CONFIG_DYNAMIC_FILE_PATH}`]
+      ) {
+        const dynamicConfigPath =
+          Settings.globalConfig[`${CONFIG_KEY}.${SETTING_CONFIG_DYNAMIC_FILE_PATH}`];
+        if (dynamicConfigPath) {
+          try {
+            await window.withProgress(
+              {
+                location: vscode.ProgressLocation.Notification,
+                title: `${EXTENSION_NAME}: Reading dynamic config file...`
+              },
+              async () => {
+                const absFilePath = Folders.getAbsFilePath(dynamicConfigPath);
+                Logger.info(`Reading dynamic config file: ${absFilePath}`);
+                if (absFilePath) {
+                  if (await existsAsync(absFilePath)) {
+                    const configFunction = require(absFilePath);
+                    const dynamicConfig = await configFunction(
+                      Object.assign({}, Settings.globalConfig)
+                    );
+
+                    if (dynamicConfig) {
+                      Settings.globalConfig = dynamicConfig;
+                      Logger.info(`Dynamic config file loaded`);
+                    }
+                  }
+                }
+              }
+            );
+          } catch (e) {
+            Logger.error(`Error reading dynamic config file: ${dynamicConfigPath}`);
+            Logger.error((e as Error).message);
+          }
+        }
+      }
     } catch (e) {
       Settings.globalConfig = undefined;
       Notifications.error(
@@ -946,8 +1015,9 @@ export class Settings {
         true
       );
       Settings.fileCreationWatcher.onDidCreate(
-        (uri) => {
-          if (parseWinPath(uri.fsPath) === parseWinPath(Settings.projectConfigPath)) {
+        async (uri) => {
+          const globalConfigPath = await Settings.projectConfigPath();
+          if (globalConfigPath && parseWinPath(uri.fsPath) === parseWinPath(globalConfigPath)) {
             Settings.onConfigChange();
             Settings.rebindWatchers();
             // Stop listening to file creation events
@@ -1027,6 +1097,15 @@ export class Settings {
     return config;
   }
 
+  /**
+   * Reload the config
+   * @param debounced
+   */
+  private static async refreshConfig() {
+    await Settings.reloadConfig();
+    Notifications.info(`Settings have been refreshed.`);
+  }
+
   /**
    * Reload the config
    * @param debounced
diff --git a/src/hooks/useContentType.tsx b/src/hooks/useContentType.tsx
index 25c630ab..a0ab0fde 100644
--- a/src/hooks/useContentType.tsx
+++ b/src/hooks/useContentType.tsx
@@ -10,7 +10,7 @@ export default function useContentType(
   const [contentType, setContentType] = useState<ContentType | null>(null);
 
   useEffect(() => {
-    if (settings) {
+    if (settings && metadata) {
       let contentTypeName = DEFAULT_CONTENT_TYPE_NAME;
 
       if (metadata?.type) {
diff --git a/src/listeners/dashboard/BaseListener.ts b/src/listeners/dashboard/BaseListener.ts
index 11166dc1..6e3fd26f 100644
--- a/src/listeners/dashboard/BaseListener.ts
+++ b/src/listeners/dashboard/BaseListener.ts
@@ -28,4 +28,12 @@ export abstract class BaseListener {
       payload
     });
   }
+
+  public static sendError(command: DashboardCommand, requestId: string, error: any) {
+    Dashboard.postWebviewMessage({
+      command,
+      requestId,
+      error
+    });
+  }
 }
diff --git a/src/listeners/dashboard/DashboardListener.ts b/src/listeners/dashboard/DashboardListener.ts
index 0a7c72d9..0ba85e54 100644
--- a/src/listeners/dashboard/DashboardListener.ts
+++ b/src/listeners/dashboard/DashboardListener.ts
@@ -4,6 +4,7 @@ import { DashboardCommand } from '../../dashboardWebView/DashboardCommand';
 import { DashboardMessage } from '../../dashboardWebView/DashboardMessage';
 import { Extension, Notifications } from '../../helpers';
 import { PostMessageData } from '../../models';
+import { PinnedItems } from '../../services';
 import { BaseListener } from './BaseListener';
 
 export class DashboardListener extends BaseListener {
@@ -29,6 +30,79 @@ export class DashboardListener extends BaseListener {
       case DashboardMessage.showWarning:
         Notifications.warning(msg.payload);
         break;
+      case DashboardMessage.pinItem:
+        DashboardListener.pinItem(msg);
+        break;
+      case DashboardMessage.unpinItem:
+        DashboardListener.unpinItem(msg);
+        break;
+      case DashboardMessage.getPinnedItems:
+        DashboardListener.getPinnedItems(msg);
+        break;
+    }
+  }
+
+  /**
+   * Get the pinned items
+   * @param msg
+   */
+  private static async getPinnedItems({ command, requestId }: PostMessageData) {
+    if (!requestId || !command) {
+      return;
+    }
+
+    const allPinned = (await PinnedItems.get()) || [];
+    this.sendRequest(command as any, requestId, allPinned);
+  }
+
+  /**
+   * Pin an item to the dashboard
+   * @param payload
+   */
+  private static async pinItem({ command, requestId, payload }: PostMessageData) {
+    if (!requestId || !command || !payload) {
+      return;
+    }
+
+    const path = payload;
+    if (!path) {
+      this.sendError(command as any, requestId, 'No path provided.');
+      return;
+    }
+
+    const allPinned = await PinnedItems.pin(path);
+
+    if (!allPinned) {
+      this.sendError(command as any, requestId, 'Could not pin item.');
+      return;
+    }
+
+    this.sendRequest(command as any, requestId, allPinned);
+  }
+
+  /**
+   * Unpin an item from the dashboard
+   * @param param0
+   * @returns
+   */
+  private static async unpinItem({ command, requestId, payload }: PostMessageData) {
+    if (!requestId || !command || !payload) {
+      return;
+    }
+
+    const path = payload;
+    if (!path) {
+      this.sendError(command as any, requestId, 'No path provided.');
+      return;
     }
+
+    const updatedPinned = await PinnedItems.remove(path);
+
+    if (!updatedPinned) {
+      this.sendError(command as any, requestId, 'Could not unpin item.');
+      return;
+    }
+
+    this.sendRequest(command as any, requestId, updatedPinned);
   }
 }
diff --git a/src/listeners/dashboard/MediaListener.ts b/src/listeners/dashboard/MediaListener.ts
index c4212921..6bec7be6 100644
--- a/src/listeners/dashboard/MediaListener.ts
+++ b/src/listeners/dashboard/MediaListener.ts
@@ -8,7 +8,9 @@ import { commands, env, Uri } from 'vscode';
 import { COMMAND_NAME, TelemetryEvent } from '../../constants';
 import * as os from 'os';
 import { Folders } from '../../commands';
-import { PostMessageData } from '../../models';
+import { PostMessageData, UnmappedMedia } from '../../models';
+import { FilesHelper, MediaLibrary } from '../../helpers';
+import { existsAsync, flattenObjectKeys } from '../../utils';
 
 export class MediaListener extends BaseListener {
   private static timers: { [folder: string]: any } = {};
@@ -49,6 +51,12 @@ export class MediaListener extends BaseListener {
         Telemetry.send(TelemetryEvent.updateMediaMetadata);
         this.update(msg.payload);
         break;
+      case DashboardMessage.getUnmappedMedia:
+        this.getUnmappedMedia(msg);
+        break;
+      case DashboardMessage.remapMediaMetadata:
+        this.remapMediaMetadata(msg);
+        break;
       case DashboardMessage.createMediaFolder:
         await commands.executeCommand(COMMAND_NAME.createFolder, msg?.payload);
         break;
@@ -71,10 +79,15 @@ export class MediaListener extends BaseListener {
     folder: string = '',
     sorting: SortingOption | null = null
   ) {
+    MediaLibrary.reset();
     const files = await MediaHelpers.getMedia(page, folder, sorting);
     this.sendMsg(DashboardCommand.media, files);
   }
 
+  /**
+   * Open file in finder or explorer
+   * @param file
+   */
   private static openFileInFinder(file: string) {
     if (file) {
       if (os.type() === 'Linux' && env.remoteName?.toLowerCase() === 'wsl') {
@@ -85,6 +98,62 @@ export class MediaListener extends BaseListener {
     }
   }
 
+  private static async remapMediaMetadata({ command, payload }: PostMessageData) {
+    if (!payload || !command) {
+      return;
+    }
+
+    const { unmappedItem, file, folder, page } = payload;
+
+    if (!unmappedItem || !(unmappedItem as UnmappedMedia).absPath || !file) {
+      return;
+    }
+
+    const mediaLib = MediaLibrary.getInstance();
+
+    await mediaLib.rename((unmappedItem as UnmappedMedia).absPath, file);
+    this.sendMediaFiles(page || 0, folder || '');
+  }
+
+  /**
+   * Find all the unmapped media file with the given name
+   * @param msg
+   */
+  private static async getUnmappedMedia({ command, payload, requestId }: PostMessageData) {
+    if (!payload || !command || !requestId) {
+      return;
+    }
+
+    const mediaLib = MediaLibrary.getInstance();
+    const allMetadata = await mediaLib.getAll();
+    const allFilePaths = flattenObjectKeys(allMetadata);
+
+    const filesEndingWith = allFilePaths.filter((f) => f.endsWith(payload));
+
+    // Check if the files exist
+    const unmappedFiles: UnmappedMedia[] = [];
+    for (const file of filesEndingWith) {
+      const absPath = FilesHelper.relToAbsPath(file);
+      if (!(await existsAsync(absPath))) {
+        const parsedPath = mediaLib.parsePath(absPath);
+        const metadata = await mediaLib.get(parsedPath);
+        if (metadata) {
+          unmappedFiles.push({
+            file,
+            absPath,
+            metadata: {
+              ...(metadata as { [key: string]: any })
+            }
+          } as UnmappedMedia);
+        }
+      }
+    }
+
+    if (unmappedFiles && unmappedFiles.length > 0) {
+      this.sendRequest(command as any, requestId, unmappedFiles);
+    }
+  }
+
   /**
    * Store the file and send a message after multiple uploads
    * @param data
diff --git a/src/listeners/dashboard/SettingsListener.ts b/src/listeners/dashboard/SettingsListener.ts
index 6eb622b3..ad0a7375 100644
--- a/src/listeners/dashboard/SettingsListener.ts
+++ b/src/listeners/dashboard/SettingsListener.ts
@@ -21,7 +21,6 @@ import { DataListener } from '../panel';
 import { MarkdownFoldingProvider } from '../../providers/MarkdownFoldingProvider';
 import { ModeSwitch } from '../../services/ModeSwitch';
 import { PagesListener } from './PagesListener';
-import { existsAsync } from '../../utils';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../localization';
 import download from 'github-directory-downloader/esm';
@@ -31,7 +30,7 @@ export class SettingsListener extends BaseListener {
    * Process the messages for the dashboard views
    * @param msg
    */
-  public static process(msg: PostMessageData) {
+  public static async process(msg: PostMessageData) {
     super.process(msg);
 
     switch (msg.command) {
@@ -56,7 +55,45 @@ export class SettingsListener extends BaseListener {
       case DashboardMessage.switchProject:
         this.switchProject(msg.payload);
         break;
+      case DashboardMessage.getSettings:
+        this.getConfigSettings(msg);
+        break;
+      case DashboardMessage.setSettings:
+        this.setConfigSettings(msg);
+        break;
+    }
+  }
+
+  public static async getConfigSettings({ command, requestId, payload }: PostMessageData) {
+    if (!command || !requestId || !payload) {
+      return;
     }
+
+    const settings = [];
+
+    for (const setting of payload) {
+      const value = Settings.get(setting);
+      settings.push({ name: setting, value });
+    }
+
+    this.sendRequest(command as any, requestId, settings);
+  }
+
+  public static async setConfigSettings({ command, requestId, payload }: PostMessageData) {
+    if (!command || !requestId || !payload) {
+      return;
+    }
+
+    for (const setting of payload) {
+      if (typeof setting.name !== 'undefined' && typeof setting.value !== 'undefined') {
+        const value = Settings.get(setting.name);
+        if (value !== setting.value) {
+          await Settings.update(setting.name, setting.value, true);
+        }
+      }
+    }
+
+    this.sendRequest(command as any, requestId, true);
   }
 
   public static async switchProject(project: string) {
diff --git a/src/listeners/dashboard/SsgListener.ts b/src/listeners/dashboard/SsgListener.ts
new file mode 100644
index 00000000..3460c386
--- /dev/null
+++ b/src/listeners/dashboard/SsgListener.ts
@@ -0,0 +1,293 @@
+import { Uri, workspace } from 'vscode';
+import { DashboardMessage } from '../../dashboardWebView/DashboardMessage';
+import { AstroCollection, AstroField, ContentType, Field, PostMessageData } from '../../models';
+import { BaseListener } from './BaseListener';
+import { exec } from 'child_process';
+import { Extension, Logger, Settings } from '../../helpers';
+import { Folders } from '../../commands';
+import { SETTING_TAXONOMY_CONTENT_TYPES, SsgScripts } from '../../constants';
+import { SettingsListener } from './SettingsListener';
+import { Terminal } from '../../services';
+import { existsAsync, readFileAsync } from '../../utils';
+
+export class SsgListener extends BaseListener {
+  /**
+   * Process the messages for the dashboard views
+   * @param msg
+   */
+  public static process(msg: PostMessageData) {
+    super.process(msg);
+
+    switch (msg.command) {
+      case DashboardMessage.ssgGetAstroContentTypes:
+        SsgListener.getAstroContentTypes(msg);
+        break;
+      case DashboardMessage.ssgSetAstroContentTypes:
+        SsgListener.ssgSetAstroContentTypes(msg);
+        break;
+    }
+  }
+
+  /**
+   * Creata a content type from the Astro content collection
+   * @param param0
+   * @returns
+   */
+  private static async ssgSetAstroContentTypes({ command, requestId, payload }: PostMessageData) {
+    if (!command || !requestId || !payload) {
+      return;
+    }
+
+    const { collection } = payload as { collection: AstroCollection };
+
+    const contentType: ContentType = {
+      name: collection.name,
+      filePrefix: undefined,
+      previewPath: undefined,
+      pageBundle: false,
+      clearEmpty: true,
+      fields: []
+    };
+
+    for (const field of collection.fields) {
+      const ctField = SsgListener.getCtFieldForAstroField(field, collection.fields);
+
+      if (ctField) {
+        contentType.fields.push(ctField);
+      }
+    }
+
+    const contentTypes = Settings.get<ContentType[]>(SETTING_TAXONOMY_CONTENT_TYPES) || [];
+
+    if (contentTypes.find((ct) => ct.name === collection.name)) {
+      SsgListener.sendRequest(command as any, requestId, {});
+      SettingsListener.getSettings(true);
+      return;
+    }
+
+    try {
+      // Check if the content folder exists
+      const folderName = `/src/content/${collection.name}`;
+      const folderUri = Uri.joinPath(Folders.getWorkspaceFolder()!, folderName);
+      await workspace.fs.readDirectory(folderUri);
+
+      await Folders.register({
+        title: collection.name,
+        path: folderUri,
+        contentType: [collection.name]
+      });
+
+      contentType.previewPath = `'${collection.name}'`;
+    } catch (e) {
+      // Something failed, so it seems the folder does not exist
+    }
+
+    contentTypes.push(contentType);
+    await Settings.update(SETTING_TAXONOMY_CONTENT_TYPES, contentTypes, true);
+
+    SsgListener.sendRequest(command as any, requestId, {});
+    SettingsListener.getSettings(true);
+  }
+
+  /**
+   * Get the Astro content types from the local project
+   * @param command
+   * @param requestId
+   */
+  private static async getAstroContentTypes({ command, requestId }: PostMessageData) {
+    if (!command || !requestId) {
+      return;
+    }
+
+    // https://github.com/withastro/astro/blob/defab70cb2a0c67d5e9153542490d2749046b151/packages/astro/src/content/utils.ts#L450
+    const contentConfig = await workspace.findFiles(`**/src/content/config.*`);
+
+    if (contentConfig.length === 0) {
+      SsgListener.sendRequest(command as any, requestId, []);
+      return;
+    }
+
+    const contentConfigFile = contentConfig[0];
+    if (
+      !contentConfigFile.fsPath.endsWith('.js') &&
+      !contentConfigFile.fsPath.endsWith('.mjs') &&
+      !contentConfigFile.fsPath.endsWith('.ts') &&
+      !contentConfigFile.fsPath.endsWith('.mts')
+    ) {
+      SsgListener.sendRequest(command as any, requestId, []);
+      return;
+    }
+
+    const scriptPath = Uri.joinPath(
+      Extension.getInstance().extensionPath,
+      SsgScripts.folder,
+      SsgScripts.astroContentCollectionScript
+    );
+
+    const wsFolder = Folders.getWorkspaceFolder();
+    if (!wsFolder) {
+      SsgListener.sendRequest(command as any, requestId, []);
+      return;
+    }
+
+    const tempLocation = Uri.joinPath(wsFolder, '/.frontmatter/temp');
+    const tempScriptPath = Uri.joinPath(tempLocation, SsgScripts.astroContentCollectionScript);
+    await workspace.fs.createDirectory(tempLocation);
+    workspace.fs.copy(scriptPath, tempScriptPath, { overwrite: true });
+
+    const fullScript = `node "${tempScriptPath.fsPath}" "${contentConfigFile.fsPath}"`;
+
+    try {
+      const result: string = await SsgListener.executeScript(fullScript, wsFolder?.fsPath || '');
+      if (result) {
+        const tempJsonPath = Uri.joinPath(tempLocation, SsgScripts.astroContentCollectionJSON);
+        if (await existsAsync(tempJsonPath.fsPath)) {
+          const contents = await readFileAsync(tempJsonPath.fsPath, 'utf8');
+          let collections: AstroCollection[] = JSON.parse(contents);
+          collections = collections.filter((c) => c.type === 'content');
+          SsgListener.sendRequest(command as any, requestId, collections);
+        }
+      }
+    } catch (error) {
+      Logger.error((error as Error).message);
+      SsgListener.sendRequest(command as any, requestId, []);
+      return;
+    } finally {
+      await workspace.fs.delete(tempLocation, { recursive: true, useTrash: false });
+    }
+  }
+
+  /**
+   * Generate the ContentType field from the Astro field
+   * @param field
+   * @param collection
+   * @returns
+   */
+  private static getCtFieldForAstroField(
+    field: AstroField,
+    collection: AstroField[]
+  ): Field | undefined {
+    let ctField: Field | undefined = undefined;
+    const hasImageField = collection.find((f) => f.type === 'image');
+
+    switch (field.type) {
+      case 'email':
+      case 'url':
+      case 'ZodString':
+        ctField = {
+          name: field.name,
+          type: 'string',
+          single: true
+        } as Field;
+        break;
+      case 'ZodNumber':
+        ctField = {
+          name: field.name,
+          type: 'number'
+        } as Field;
+        break;
+      case 'ZodBoolean':
+        ctField = {
+          name: field.name,
+          type: 'boolean'
+        } as Field;
+        break;
+      case 'ZodArray':
+        ctField = {
+          name: field.name,
+          type: 'list'
+        } as Field;
+        break;
+      case 'ZodEnum':
+        ctField = {
+          name: field.name,
+          type: 'choice',
+          choices: field.options || []
+        } as Field;
+        break;
+      case 'ZodDate':
+        ctField = {
+          name: field.name,
+          type: 'datetime',
+          default: '{{now}}'
+        } as Field;
+        break;
+      case 'image':
+        ctField = {
+          name: field.name,
+          type: 'image'
+        } as Field;
+        break;
+      case 'ZodObject':
+        ctField = {
+          name: field.name,
+          type: 'fields'
+        } as Field;
+        break;
+    }
+
+    if (field.type === 'ZodObject' && field.fields) {
+      ctField.fields = [];
+      for (const subField of field.fields) {
+        const ctSubField = SsgListener.getCtFieldForAstroField(subField, collection);
+
+        if (ctSubField) {
+          ctField.fields.push(ctSubField);
+        }
+      }
+    }
+
+    if (ctField && field.required) {
+      ctField.required = field.required;
+    }
+
+    if (ctField && field.defaultValue) {
+      ctField.default = field.defaultValue;
+    }
+
+    if (ctField && field.description) {
+      ctField.description = field.description;
+    }
+
+    if (ctField && field.type === 'image' && !hasImageField) {
+      ctField.isPreviewImage = true;
+    }
+
+    return ctField;
+  }
+
+  /**
+   * Execute a script
+   * @param fullScript
+   * @param wsFolder
+   * @returns
+   */
+  private static executeScript(fullScript: string, wsFolder: string): Promise<string> {
+    return new Promise((resolve, reject) => {
+      Logger.info(`Executing script: ${fullScript}`);
+
+      const shellPath: string | { path: string } | undefined = Terminal.shell;
+
+      exec(
+        fullScript,
+        {
+          cwd: wsFolder,
+          shell: shellPath
+        },
+        (error, stdout) => {
+          if (error) {
+            reject(error);
+            return;
+          }
+
+          if (stdout && stdout.endsWith(`\n`)) {
+            // Remove empty line at the end of the string
+            stdout = stdout.slice(0, -1);
+          }
+
+          resolve(stdout);
+        }
+      );
+    });
+  }
+}
diff --git a/src/listeners/dashboard/index.ts b/src/listeners/dashboard/index.ts
index 2e373d4a..230a62c6 100644
--- a/src/listeners/dashboard/index.ts
+++ b/src/listeners/dashboard/index.ts
@@ -10,3 +10,4 @@ export * from './TelemetryListener';
 export * from './TaxonomyListener';
 export * from './LogListener';
 export * from './LocalizationListener';
+export * from './SsgListener';
diff --git a/src/listeners/panel/DataListener.ts b/src/listeners/panel/DataListener.ts
index 28d9a039..a8acee27 100644
--- a/src/listeners/panel/DataListener.ts
+++ b/src/listeners/panel/DataListener.ts
@@ -153,7 +153,10 @@ export class DataListener extends BaseListener {
    */
   public static async pushMetadata(metadata: any) {
     const wsFolder = Folders.getWorkspaceFolder();
-    const filePath = window.activeTextEditor?.document.uri.fsPath || Preview.filePath;
+    const filePath =
+      window.activeTextEditor?.document.uri.fsPath ||
+      Preview.filePath ||
+      ArticleHelper.getActiveFile();
     const commaSeparated = Settings.get<string[]>(SETTING_COMMA_SEPARATED_FIELDS);
     const contentTypes = Settings.get<string>(SETTING_TAXONOMY_CONTENT_TYPES);
 
diff --git a/src/listeners/panel/FieldsListener.ts b/src/listeners/panel/FieldsListener.ts
index 27912d99..5c4191d6 100644
--- a/src/listeners/panel/FieldsListener.ts
+++ b/src/listeners/panel/FieldsListener.ts
@@ -43,7 +43,8 @@ export class FieldsListener extends BaseListener {
         ExtensionState.Dashboard.Pages.Index,
         'workspace'
       );
-      const fuse = new Fuse(pages || [], fuseOptions, Fuse.parseIndex(pagesIndex));
+      const fuseIndex = Fuse.parseIndex(pagesIndex);
+      const fuse = new Fuse(pages || [], fuseOptions, fuseIndex);
       const results = fuse.search({
         $and: [
           {
diff --git a/src/listeners/panel/MediaListener.ts b/src/listeners/panel/MediaListener.ts
index 49775127..1fb79529 100644
--- a/src/listeners/panel/MediaListener.ts
+++ b/src/listeners/panel/MediaListener.ts
@@ -2,7 +2,7 @@ import { PanelProvider } from './../../panelWebView/PanelProvider';
 import { commands, window } from 'vscode';
 import { Dashboard } from '../../commands/Dashboard';
 import { COMMAND_NAME } from '../../constants';
-import { ImageHelper } from '../../helpers';
+import { ArticleHelper, ImageHelper } from '../../helpers';
 import { DashboardData, PostMessageData } from '../../models';
 import { Command } from '../../panelWebView/Command';
 import { CommandToCode } from '../../panelWebView/CommandToCode';
@@ -42,7 +42,10 @@ export class MediaListener extends BaseListener {
 
     if (typeof payload === 'string') {
       const imagePath = payload;
-      const filePath = window.activeTextEditor?.document.uri.fsPath || Preview.filePath;
+      const filePath =
+        window.activeTextEditor?.document.uri.fsPath ||
+        Preview.filePath ||
+        ArticleHelper.getActiveFile();
       if (!filePath) {
         return;
       }
diff --git a/src/localization/localization.enum.ts b/src/localization/localization.enum.ts
index 7699122d..64c5e11c 100644
--- a/src/localization/localization.enum.ts
+++ b/src/localization/localization.enum.ts
@@ -83,6 +83,10 @@ export enum LocalizationKey {
    * Remove {0}
    */
   commonRemoveValue = 'common.remove.value',
+  /**
+   * Filter by {0}
+   */
+  commonFilterValue = 'common.filter.value',
   /**
    * Sorry, something went wrong.
    */
@@ -91,6 +95,74 @@ export enum LocalizationKey {
    * Open on website
    */
   commonOpenOnWebsite = 'common.openOnWebsite',
+  /**
+   * Settings
+   */
+  commonSettings = 'common.settings',
+  /**
+   * Refresh settings
+   */
+  commonRefreshSettings = 'common.refreshSettings',
+  /**
+   * Pin
+   */
+  commonPin = 'common.pin',
+  /**
+   * Unpin
+   */
+  commonUnpin = 'common.unpin',
+  /**
+   * Common
+   */
+  settingsViewCommon = 'settings.view.common',
+  /**
+   * Content folders
+   */
+  settingsViewContentFolders = 'settings.view.contentFolders',
+  /**
+   * Astro
+   */
+  settingsViewAstro = 'settings.view.astro',
+  /**
+   * Open dashboard on startup
+   */
+  settingsOpenOnStartup = 'settings.openOnStartup',
+  /**
+   * Content types
+   */
+  settingsContentTypes = 'settings.contentTypes',
+  /**
+   * Content folders
+   */
+  settingsContentFolders = 'settings.contentFolders',
+  /**
+   * Diagnostic
+   */
+  settingsDiagnostic = 'settings.diagnostic',
+  /**
+   * You can run the diagnostics to check the whole Front Matter CMS configuration.
+   */
+  settingsDiagnosticDescription = 'settings.diagnostic.description',
+  /**
+   * Run full diagnostics
+   */
+  settingsDiagnosticLink = 'settings.diagnostic.link',
+  /**
+   * Website and SSG settings
+   */
+  settingsCommonSettingsWebsiteTitle = 'settings.commonSettings.website.title',
+  /**
+   * Preview URL
+   */
+  settingsCommonSettingsPreviewUrl = 'settings.commonSettings.previewUrl',
+  /**
+   * Website URL
+   */
+  settingsCommonSettingsWebsiteUrl = 'settings.commonSettings.websiteUrl',
+  /**
+   * SSG/Framework start command
+   */
+  settingsCommonSettingsStartCommand = 'settings.commonSettings.startCommand',
   /**
    * Developer mode
    */
@@ -199,6 +271,10 @@ export enum LocalizationKey {
    * Make sure you registered a content folder in your project to let Front Matter find the contents.
    */
   dashboardContentsOverviewNoFolders = 'dashboard.contents.overview.noFolders',
+  /**
+   * Pinned
+   */
+  dashboardContentsOverviewPinned = 'dashboard.contents.overview.pinned',
   /**
    * Draft
    */
@@ -803,6 +879,10 @@ export enum LocalizationKey {
    * Select a template to prefill the frontmatter.json file with the recommended settings.
    */
   dashboardStepsStepsToGetStartedTemplateDescription = 'dashboard.steps.stepsToGetStarted.template.description',
+  /**
+   * Create Content-Types for your Astro Content Collections
+   */
+  dashboardStepsStepsToGetStartedAstroContentTypesName = 'dashboard.steps.stepsToGetStarted.astroContentTypes.name',
   /**
    * Add {0} to taxonomy settings
    */
@@ -896,9 +976,13 @@ export enum LocalizationKey {
    */
   dashboardWelcomeScreenLinkGithubTitle = 'dashboard.welcomeScreen.link.github.title',
   /**
-   * GitHub / Documentation
+   * GitHub
    */
   dashboardWelcomeScreenLinkGithubLabel = 'dashboard.welcomeScreen.link.github.label',
+  /**
+   * Documentation
+   */
+  dashboardWelcomeScreenLinkDocumentationLabel = 'dashboard.welcomeScreen.link.documentation.label',
   /**
    * Become a sponsor
    */
@@ -927,6 +1011,18 @@ export enum LocalizationKey {
    * We hope you enjoy Front Matter!
    */
   dashboardWelcomeScreenActionsThanks = 'dashboard.welcomeScreen.actions.thanks',
+  /**
+   * Do you want to remap the metadata of unmapped files?
+   */
+  dashboardMediaDetailsSlideOverUnmappedDescription = 'dashboard.media.detailsSlideOver.unmapped.description',
+  /**
+   * No Astro Content Collections found.
+   */
+  dashboardConfigurationAstroAstroContentTypesEmpty = 'dashboard.configuration.astro.astroContentTypes.empty',
+  /**
+   * The following Astro Content Collections and can be used to generate a content-type.
+   */
+  dashboardConfigurationAstroAstroContentTypesDescription = 'dashboard.configuration.astro.astroContentTypes.description',
   /**
    * Content-type
    */
@@ -1112,10 +1208,6 @@ export enum LocalizationKey {
    * Open dashboard
    */
   panelBaseViewActionOpenDashboard = 'panel.baseView.action.openDashboard',
-  /**
-   * Open preview
-   */
-  panelBaseViewActionOpenPreview = 'panel.baseView.action.openPreview',
   /**
    * Create content
    */
diff --git a/src/models/AstroCollections.ts b/src/models/AstroCollections.ts
new file mode 100644
index 00000000..f07b9c3f
--- /dev/null
+++ b/src/models/AstroCollections.ts
@@ -0,0 +1,25 @@
+export interface AstroCollection {
+  name: string;
+  type: 'content' | 'data';
+  fields: AstroField[];
+}
+
+export interface AstroField {
+  name: string;
+  type:
+    | 'ZodString'
+    | 'ZodNumber'
+    | 'ZodBoolean'
+    | 'ZodArray'
+    | 'ZodEnum'
+    | 'ZodDate'
+    | 'ZodObject'
+    | 'email'
+    | 'url'
+    | 'image';
+  required: boolean;
+  defaultValue?: string;
+  options?: string[];
+  description?: string;
+  fields?: AstroField[];
+}
diff --git a/src/models/ContentFolder.ts b/src/models/ContentFolder.ts
index 74e9e8d5..734245a8 100644
--- a/src/models/ContentFolder.ts
+++ b/src/models/ContentFolder.ts
@@ -2,6 +2,7 @@ export interface ContentFolder {
   title: string;
   path: string;
 
+  disableCreation?: boolean;
   excludeSubdir?: boolean;
   previewPath?: string;
   filePrefix?: string;
diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts
index c0a084a8..b7dbb7bb 100644
--- a/src/models/PanelSettings.ts
+++ b/src/models/PanelSettings.ts
@@ -31,8 +31,18 @@ export interface PanelSettings {
   aiEnabled: boolean;
   contentFolders: ContentFolder[];
   websiteUrl: string;
+  disabledActions: PanelAction[];
 }
 
+export type PanelAction =
+  | 'openDashboard'
+  | 'createContent'
+  | 'optimizeSlug'
+  | 'preview'
+  | 'openOnWebsite'
+  | 'startStopServer'
+  | 'customActions';
+
 export interface FieldGroup {
   id: string;
   labelField?: string;
@@ -78,6 +88,7 @@ export type FieldType =
   | 'divider'
   | 'heading'
   | 'contentRelationship'
+  | 'fieldCollection'
   | 'customField';
 
 export interface Field {
@@ -196,6 +207,7 @@ export interface CustomScript {
   command?: CommandType | string;
   hidden?: boolean;
   environments?: EnvironmentScript[];
+  contentTypes?: string[];
 }
 
 export type EnvironmentType = 'windows' | 'macos' | 'linux';
diff --git a/src/models/PostMessageData.ts b/src/models/PostMessageData.ts
index 9fd0b412..cb3c2912 100644
--- a/src/models/PostMessageData.ts
+++ b/src/models/PostMessageData.ts
@@ -1,5 +1,5 @@
-export interface PostMessageData { 
-  command: string; 
-  payload: any; 
-  requestId?: string 
-}
\ No newline at end of file
+export interface PostMessageData {
+  command: string;
+  payload: any;
+  requestId?: string;
+}
diff --git a/src/models/UnmappedMedia.ts b/src/models/UnmappedMedia.ts
new file mode 100644
index 00000000..8536a6b1
--- /dev/null
+++ b/src/models/UnmappedMedia.ts
@@ -0,0 +1,8 @@
+export interface UnmappedMedia {
+  file: string;
+  absPath: string;
+  metadata: {
+    title: string;
+    [prop: string]: string;
+  };
+}
diff --git a/src/models/index.ts b/src/models/index.ts
index 3d60f8c2..68886aa7 100644
--- a/src/models/index.ts
+++ b/src/models/index.ts
@@ -1,3 +1,4 @@
+export * from './AstroCollections';
 export * from './BaseFieldProps';
 export * from './BlockFieldData';
 export * from './Choice';
@@ -25,4 +26,5 @@ export * from './StaticFolder';
 export * from './TaxonomyData';
 export * from './TaxonomyType';
 export * from './Template';
+export * from './UnmappedMedia';
 export * from './VersionInfo';
diff --git a/src/panelWebView/PanelProvider.ts b/src/panelWebView/PanelProvider.ts
index 98fb27d8..0f8630c3 100644
--- a/src/panelWebView/PanelProvider.ts
+++ b/src/panelWebView/PanelProvider.ts
@@ -20,7 +20,7 @@ import {
   WebviewViewResolveContext,
   window
 } from 'vscode';
-import { Logger, Settings } from '../helpers';
+import { ArticleHelper, Logger, Settings } from '../helpers';
 import { Command } from '../panelWebView/Command';
 import { TagType } from '../panelWebView/TagType';
 import { WebviewHelper } from '@estruyf/vscode';
@@ -28,6 +28,7 @@ import { Extension } from '../helpers/Extension';
 import { Telemetry } from '../helpers/Telemetry';
 import { GitListener, ModeListener } from '../listeners/general';
 import { Folders } from '../commands';
+import { basename } from 'path';
 
 export class PanelProvider implements WebviewViewProvider, Disposable {
   public static readonly viewType = 'frontMatter.explorer';
@@ -96,6 +97,8 @@ export class PanelProvider implements WebviewViewProvider, Disposable {
       }, this)
     );
 
+    this.updateCurrentFile();
+
     webviewView.webview.onDidReceiveMessage(async (msg) => {
       Logger.info(`Receiving message from webview to panel: ${msg.command}`);
 
@@ -159,15 +162,43 @@ export class PanelProvider implements WebviewViewProvider, Disposable {
     this.sendMessage({ command: Command.closeSections });
   }
 
-  private counts(acc: any, node: any) {
-    // add 1 to an initial or existing value
-    acc[node.type] = (acc[node.type] || 0) + 1;
+  /**
+   * On view change, update the current file that is loaded to show the correct data
+   */
+  public async updateCurrentFile() {
+    const crntPanel = PanelProvider.getInstance();
+    if (!crntPanel.visible) {
+      return;
+    }
+
+    const filePath = ArticleHelper.getActiveFile();
+    if (filePath) {
+      const article = await ArticleHelper.getFrontMatterByPath(filePath);
+      DataListener.pushMetadata(article?.data);
 
-    // find and add up the counts from all of this node's children
-    return (node.children || []).reduce(
-      (childAcc: any, childNode: any) => this.counts(childAcc, childNode),
-      acc
-    );
+      const fileName = basename(filePath);
+      crntPanel.updateTitle(fileName);
+    } else {
+      crntPanel.updateTitle(undefined);
+    }
+  }
+
+  /**
+   * Update the title of the panel
+   * @param title
+   * @returns
+   */
+  private updateTitle(title: string | undefined) {
+    if (!this.panel) {
+      return;
+    }
+
+    if (!title) {
+      this.panel.title = 'General';
+      return;
+    }
+
+    this.panel.title = title;
   }
 
   /**
diff --git a/src/panelWebView/ViewPanel.tsx b/src/panelWebView/ViewPanel.tsx
index edc9e3dc..de78eb23 100644
--- a/src/panelWebView/ViewPanel.tsx
+++ b/src/panelWebView/ViewPanel.tsx
@@ -134,7 +134,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
         )}
         {settings && metadata && (
           <FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.panel.actions}>
-            <Actions metadata={metadata} settings={settings} />
+            <Actions metadata={metadata} settings={settings} scripts={settings.scripts} />
           </FeatureFlag>
         )}
 
diff --git a/src/panelWebView/components/Actions.tsx b/src/panelWebView/components/Actions.tsx
index 09a1fd90..fa62f05d 100644
--- a/src/panelWebView/components/Actions.tsx
+++ b/src/panelWebView/components/Actions.tsx
@@ -1,5 +1,5 @@
 import * as React from 'react';
-import { PanelSettings } from '../../models/PanelSettings';
+import { PanelSettings, CustomScript as ICustomScript } from '../../models';
 import { Collapsible } from './Collapsible';
 import { CustomScript } from './CustomScript';
 import { Preview } from './Preview';
@@ -8,38 +8,115 @@ import { StartServerButton } from './StartServerButton';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../localization';
 import { OpenOnWebsiteAction } from './Actions/OpenOnWebsiteAction';
+import useContentType from '../../hooks/useContentType';
+import { messageHandler } from '@estruyf/vscode/dist/client';
+import { CommandToCode } from '../CommandToCode';
 
 export interface IActionsProps {
-  metadata: any;
+  metadata?: any;
   settings: PanelSettings;
+  scripts?: ICustomScript[];
 }
 
 const Actions: React.FunctionComponent<IActionsProps> = ({
   metadata,
-  settings
+  settings,
+  scripts = []
 }: React.PropsWithChildren<IActionsProps>) => {
-  if (!metadata || Object.keys(metadata).length === 0 || !settings) {
+  const contentType = useContentType(settings, metadata);
+  const disableActions = settings.disabledActions || [];
+
+  const openDashboard = () => {
+    messageHandler.send(CommandToCode.openDashboard);
+  };
+
+  const createContent = () => {
+    messageHandler.send(CommandToCode.createContent);
+  };
+
+  const actions = React.useMemo(() => {
+    let allActions: JSX.Element[] = [];
+
+    if (!disableActions.includes(`openDashboard`)) {
+      allActions.push(
+        <button
+          title={l10n.t(LocalizationKey.panelBaseViewActionOpenDashboard)}
+          onClick={openDashboard}
+          type={`button`}>
+          {l10n.t(LocalizationKey.panelBaseViewActionOpenDashboard)}
+        </button>
+      );
+    }
+
+    if (metadata?.title && !disableActions.includes(`optimizeSlug`)) {
+      allActions.push(<SlugAction key="optimizeSlug" />);
+    }
+
+    if (settings?.preview?.host && !disableActions.includes(`preview`)) {
+      if ((metadata && metadata.slug) || !metadata) {
+        allActions.push(<Preview key="preview" />);
+      }
+    }
+
+    if (!disableActions.includes(`openOnWebsite`) && metadata?.slug) {
+      allActions.push(<OpenOnWebsiteAction key="openOnWebsite" baseUrl={settings.websiteUrl} slug={metadata.slug} />);
+    }
+
+    if (!disableActions.includes(`startStopServer`)) {
+      allActions.push(<StartServerButton key="startStopServer" settings={settings} />);
+    }
+
+    if (!disableActions.includes(`createContent`)) {
+      allActions.push(
+        <button
+          title={l10n.t(LocalizationKey.panelBaseViewActionCreateContent)}
+          onClick={createContent}
+          type={`button`}>
+          {l10n.t(LocalizationKey.panelBaseViewActionCreateContent)}
+        </button>
+      );
+    }
+
+    return allActions;
+  }, [metadata, settings, disableActions]);
+
+
+  const customActions = React.useMemo(() => {
+    let allActions: JSX.Element[] = [];
+
+    if (!disableActions.includes(`customActions`)) {
+      if (contentType?.name) {
+        scripts = scripts.filter((script) => {
+          if (script.contentTypes && script.contentTypes.length > 0) {
+            return script.contentTypes.includes(contentType.name);
+          }
+
+          return true;
+        });
+      }
+
+      allActions = scripts.map((value, idx) => (
+        <CustomScript key={value?.title?.replace(/ /g, '') || idx} {...value} />
+      ))
+    }
+
+    return allActions;
+  }, [scripts, contentType, disableActions]);
+
+  if (!settings || (customActions.length === 0 && actions.length === 0)) {
     return null;
   }
 
   return (
     <Collapsible id={`actions`} title={l10n.t(LocalizationKey.panelActionsTitle)}>
       <div className={`article__actions`}>
-        {metadata && metadata.title && <SlugAction />}
-
-        {settings?.preview?.host && <Preview slug={metadata.slug} />}
-
-        <OpenOnWebsiteAction baseUrl={settings.websiteUrl} slug={metadata.slug} />
-
-        <StartServerButton settings={settings} />
+        {...actions}
 
-        {settings && settings.scripts && settings.scripts.length > 0 && (
+        {customActions?.length > 0 && (
           <>
-            <div className="divider py-4 w-full" style={{ height: `1px` }}></div>
+            {actions?.length > 0 && <div className="divider py-4 w-full" style={{ height: `1px` }}></div>}
 
-            {settings.scripts.map((value, idx) => (
-              <CustomScript key={value?.title?.replace(/ /g, '') || idx} {...value} />
-            ))}
+            {...customActions}
           </>
         )}
       </div>
diff --git a/src/panelWebView/components/BaseView.tsx b/src/panelWebView/components/BaseView.tsx
index 632a427e..5821bdbd 100644
--- a/src/panelWebView/components/BaseView.tsx
+++ b/src/panelWebView/components/BaseView.tsx
@@ -1,20 +1,17 @@
 import * as React from 'react';
-import { CustomScript, FolderInfo, Mode, PanelSettings } from '../../models';
-import { CommandToCode } from '../CommandToCode';
-import { Collapsible } from './Collapsible';
+import { FolderInfo, Mode, PanelSettings } from '../../models';
 import { GlobalSettings } from './GlobalSettings';
 import { OtherActions } from './OtherActions';
 import { FolderAndFiles } from './FolderAndFiles';
 import { SponsorMsg } from './SponsorMsg';
-import { StartServerButton } from './StartServerButton';
 import { FeatureFlag } from '../../components/features/FeatureFlag';
 import { FEATURE_FLAG } from '../../constants/Features';
-import { Messenger } from '@estruyf/vscode/dist/client';
 import { GitAction } from './Git/GitAction';
 import { useMemo } from 'react';
 import * as l10n from "@vscode/l10n"
 import { LocalizationKey } from '../../localization';
 import { InitializeAction } from './InitializeAction';
+import { Actions } from './Actions';
 
 export interface IBaseViewProps {
   settings: PanelSettings | undefined;
@@ -27,25 +24,6 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
   folderAndFiles,
   mode
 }: React.PropsWithChildren<IBaseViewProps>) => {
-  const openDashboard = () => {
-    Messenger.send(CommandToCode.openDashboard);
-  };
-
-  const createContent = () => {
-    Messenger.send(CommandToCode.createContent);
-  };
-
-  const openPreview = () => {
-    Messenger.send(CommandToCode.openPreview);
-  };
-
-  const runBulkScript = (script: CustomScript) => {
-    Messenger.send(CommandToCode.runCustomScript, {
-      title: script.title,
-      script
-    });
-  };
-
   const customActions: any[] = (settings?.scripts || []).filter(
     (s) => s.bulk && (s.type === 'content' || !s.type)
   );
@@ -83,43 +61,7 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
             </FeatureFlag>
 
             <FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.panel.actions}>
-              <Collapsible id={`base_actions`} title={l10n.t(LocalizationKey.panelBaseViewActionsTitle)}>
-                <div className={`base__actions`}>
-                  <button
-                    title={l10n.t(LocalizationKey.panelBaseViewActionOpenDashboard)}
-                    onClick={openDashboard}
-                    type={`button`}>
-                    {l10n.t(LocalizationKey.panelBaseViewActionOpenDashboard)}
-                  </button>
-
-                  <button
-                    title={l10n.t(LocalizationKey.panelBaseViewActionOpenPreview)}
-                    onClick={openPreview}
-                    disabled={!settings?.preview?.host}
-                    type={`button`}>
-                    {l10n.t(LocalizationKey.panelBaseViewActionOpenPreview)}
-                  </button>
-
-                  <StartServerButton settings={settings} />
-
-                  <button
-                    title={l10n.t(LocalizationKey.panelBaseViewActionCreateContent)}
-                    onClick={createContent}
-                    type={`button`}>
-                    {l10n.t(LocalizationKey.panelBaseViewActionCreateContent)}
-                  </button>
-
-                  {customActions.map((script) => (
-                    <button
-                      key={script.title}
-                      title={script.title}
-                      type={`button`}
-                      onClick={() => runBulkScript(script)}>
-                      {script.title}
-                    </button>
-                  ))}
-                </div>
-              </Collapsible>
+              <Actions settings={settings} scripts={customActions} />
             </FeatureFlag>
           </>
         )}
diff --git a/src/panelWebView/components/Fields/ChoiceField.tsx b/src/panelWebView/components/Fields/ChoiceField.tsx
index 7ce301e3..cbbd4777 100644
--- a/src/panelWebView/components/Fields/ChoiceField.tsx
+++ b/src/panelWebView/components/Fields/ChoiceField.tsx
@@ -9,6 +9,7 @@ import { FieldTitle } from './FieldTitle';
 import { FieldMessage } from './FieldMessage';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import useDropdownStyle from '../../hooks/useDropdownStyle';
 
 export interface IChoiceFieldProps extends BaseFieldProps<string | string[]> {
   choices: string[] | Choice[];
@@ -27,6 +28,8 @@ export const ChoiceField: React.FunctionComponent<IChoiceFieldProps> = ({
 }: React.PropsWithChildren<IChoiceFieldProps>) => {
   const [crntSelected, setCrntSelected] = React.useState<string | string[] | null>(value);
   const dsRef = React.useRef<Downshift<string> | null>(null);
+  const inputRef = React.useRef<HTMLInputElement | null>(null);
+  const { getDropdownStyle } = useDropdownStyle(inputRef as any);
 
   const onValueChange = (txtValue: string) => {
     if (multiSelect) {
@@ -105,6 +108,7 @@ export const ChoiceField: React.FunctionComponent<IChoiceFieldProps> = ({
         {({ getToggleButtonProps, getItemProps, getMenuProps, isOpen, getRootProps }) => (
           <div
             {...getRootProps(undefined, { suppressRefError: true })}
+            ref={inputRef}
             className={`metadata_field__choice`}
           >
             <button
@@ -118,11 +122,14 @@ export const ChoiceField: React.FunctionComponent<IChoiceFieldProps> = ({
             </button>
 
             <ul
-              className={`metadata_field__choice_list ${isOpen ? 'open' : 'closed'}`}
+              className={`field_dropdown metadata_field__choice_list ${isOpen ? 'open' : 'closed'}`}
+              style={{
+                bottom: getDropdownStyle(isOpen)
+              }}
               {...getMenuProps()}
             >
-              {isOpen
-                ? availableChoices.map((choice, index) => (
+              {
+                availableChoices.map((choice, index) => (
                   <li
                     {...getItemProps({
                       key: getValue(choice, 'id'),
@@ -137,7 +144,7 @@ export const ChoiceField: React.FunctionComponent<IChoiceFieldProps> = ({
                     )}
                   </li>
                 ))
-                : null}
+              }
             </ul>
           </div>
         )}
diff --git a/src/panelWebView/components/Fields/ContentTypeRelationshipField.tsx b/src/panelWebView/components/Fields/ContentTypeRelationshipField.tsx
index d3891177..da353a8d 100644
--- a/src/panelWebView/components/Fields/ContentTypeRelationshipField.tsx
+++ b/src/panelWebView/components/Fields/ContentTypeRelationshipField.tsx
@@ -11,6 +11,7 @@ import { CommandToCode } from '../../CommandToCode';
 import { Page } from '../../../dashboardWebView/models';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import useDropdownStyle from '../../hooks/useDropdownStyle';
 
 export interface IContentTypeRelationshipFieldProps extends BaseFieldProps<string | string[]> {
   contentTypeName?: string;
@@ -34,12 +35,16 @@ export const ContentTypeRelationshipField: React.FunctionComponent<IContentTypeR
   const [pages, setPages] = React.useState<Page[]>([]);
   const [crntSelected, setCrntSelected] = React.useState<string | string[] | null>(value);
   const dsRef = React.useRef<Downshift<string> | null>(null);
+  const inputRef = React.useRef<HTMLInputElement | null>(null);
+  const { getDropdownStyle } = useDropdownStyle(inputRef as any);
 
   const onValueChange = (txtValue: string) => {
     if (multiSelect) {
-      const newValue = [...((crntSelected || []) as string[]), txtValue];
-      setCrntSelected(newValue);
-      onChange(newValue);
+      const crntValue = typeof crntSelected === 'string' ? [crntSelected] : crntSelected;
+      const newValue = [...((crntValue || []) as string[]), txtValue];
+      const uniqueValues = [...new Set(newValue)];
+      setCrntSelected(uniqueValues);
+      onChange(uniqueValues);
     } else {
       setCrntSelected(txtValue);
       onChange(txtValue);
@@ -77,20 +82,19 @@ export const ContentTypeRelationshipField: React.FunctionComponent<IContentTypeR
   }, [choices, contentTypeValue]);
 
   const availableChoices = useMemo(() => {
-    return !multiSelect
-      ? pages
-      : pages.filter((page: Page) => {
-        const value = page.fmFilePath;
-
-        if (typeof crntSelected === 'string') {
-          return crntSelected !== `${value}`;
-        } else if (crntSelected instanceof Array) {
-          return crntSelected.indexOf(`${value}`) === -1;
-        }
+    return pages.filter((page: Page) => {
+      const value = contentTypeValue === "slug" ? page.slug : page.fmFilePath;
+
+      if (typeof crntSelected === 'string') {
+        return crntSelected !== `${value}` && !value.includes(crntSelected);
+      } else if (crntSelected instanceof Array) {
+        const selected = crntSelected.filter((v) => v === `${value}` || value.includes(v));
+        return selected.length === 0;
+      }
 
-        return true;
-      });
-  }, [choices, crntSelected, multiSelect]);
+      return true;
+    });
+  }, [choices, crntSelected, multiSelect, contentTypeValue]);
 
   const showRequiredState = useMemo(() => {
     return (
@@ -142,6 +146,7 @@ export const ContentTypeRelationshipField: React.FunctionComponent<IContentTypeR
               {({ getToggleButtonProps, getItemProps, getMenuProps, isOpen, getRootProps }) => (
                 <div
                   {...getRootProps(undefined, { suppressRefError: true })}
+                  ref={inputRef}
                   className={`metadata_field__choice`}
                 >
                   <button
@@ -155,11 +160,14 @@ export const ContentTypeRelationshipField: React.FunctionComponent<IContentTypeR
                   </button>
 
                   <ul
-                    className={`metadata_field__choice_list ${isOpen ? 'open' : 'closed'}`}
+                    className={`field_dropdown metadata_field__choice_list ${isOpen ? 'open' : 'closed'}`}
+                    style={{
+                      bottom: getDropdownStyle(isOpen)
+                    }}
                     {...getMenuProps()}
                   >
-                    {isOpen
-                      ? availableChoices.map((choice: Page, index) => (
+                    {
+                      availableChoices.map((choice: Page, index) => (
                         <li
                           {...getItemProps({
                             key: getValue(choice, contentTypeValue),
@@ -174,7 +182,7 @@ export const ContentTypeRelationshipField: React.FunctionComponent<IContentTypeR
                           )}
                         </li>
                       ))
-                      : null}
+                    }
                   </ul>
                 </div>
               )}
diff --git a/src/panelWebView/components/Fields/DataFileField.tsx b/src/panelWebView/components/Fields/DataFileField.tsx
index 8bfef577..2cf873dd 100644
--- a/src/panelWebView/components/Fields/DataFileField.tsx
+++ b/src/panelWebView/components/Fields/DataFileField.tsx
@@ -9,6 +9,7 @@ import { FieldTitle } from './FieldTitle';
 import { FieldMessage } from './FieldMessage';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../../localization';
+import useDropdownStyle from '../../hooks/useDropdownStyle';
 
 export interface IDataFileFieldProps {
   label: string;
@@ -36,6 +37,8 @@ export const DataFileField: React.FunctionComponent<IDataFileFieldProps> = ({
   const [dataEntries, setDataEntries] = useState<string[] | null>(null);
   const [crntSelected, setCrntSelected] = React.useState<string | string[] | null>();
   const dsRef = React.useRef<Downshift<string> | null>(null);
+  const inputRef = React.useRef<HTMLInputElement | null>(null);
+  const { getDropdownStyle } = useDropdownStyle(inputRef as any);
 
   const onValueChange = useCallback(
     (txtValue: string) => {
@@ -149,6 +152,7 @@ export const DataFileField: React.FunctionComponent<IDataFileFieldProps> = ({
         {({ getToggleButtonProps, getItemProps, getMenuProps, isOpen, getRootProps }) => (
           <div
             {...getRootProps(undefined, { suppressRefError: true })}
+            ref={inputRef}
             className={`metadata_field__choice`}
           >
             <button
@@ -163,10 +167,13 @@ export const DataFileField: React.FunctionComponent<IDataFileFieldProps> = ({
 
             <ul
               className={`metadata_field__choice_list ${isOpen ? 'open' : 'closed'}`}
+              style={{
+                bottom: getDropdownStyle(isOpen)
+              }}
               {...getMenuProps()}
             >
-              {isOpen
-                ? availableChoices.map((choice, index) => (
+              {
+                availableChoices.map((choice, index) => (
                   <li
                     {...getItemProps({
                       key: choice.id,
@@ -181,7 +188,7 @@ export const DataFileField: React.FunctionComponent<IDataFileFieldProps> = ({
                     )}
                   </li>
                 ))
-                : null}
+              }
             </ul>
           </div>
         )}
diff --git a/src/panelWebView/components/Preview.tsx b/src/panelWebView/components/Preview.tsx
index 0a453562..5b8629f1 100644
--- a/src/panelWebView/components/Preview.tsx
+++ b/src/panelWebView/components/Preview.tsx
@@ -5,21 +5,13 @@ import { ActionButton } from './ActionButton';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../localization';
 
-export interface IPreviewProps {
-  slug: string;
-}
+export interface IPreviewProps { }
 
-const Preview: React.FunctionComponent<IPreviewProps> = ({
-  slug
-}: React.PropsWithChildren<IPreviewProps>) => {
+const Preview: React.FunctionComponent<IPreviewProps> = (_: React.PropsWithChildren<IPreviewProps>) => {
   const open = () => {
     Messenger.send(CommandToCode.openPreview);
   };
 
-  if (!slug) {
-    return null;
-  }
-
   return <ActionButton onClick={open} title={l10n.t(LocalizationKey.panelPreviewTitle)} />;
 };
 
diff --git a/src/panelWebView/components/Spinner.tsx b/src/panelWebView/components/Spinner.tsx
index 73199b02..b81380dc 100644
--- a/src/panelWebView/components/Spinner.tsx
+++ b/src/panelWebView/components/Spinner.tsx
@@ -8,8 +8,10 @@ const Spinner: React.FunctionComponent<ISpinnerProps> = (
   _: React.PropsWithChildren<ISpinnerProps>
 ) => {
   return (
-    <div className="spinner">
-      {l10n.t(LocalizationKey.panelSpinnerLoading)}
+    <div className="vscode__loader">
+      <div className="vscode__loader__bar">
+        <div className="vscode__loader__bar__animation"></div>
+      </div>
     </div>
   );
 };
diff --git a/src/panelWebView/components/TagPicker.tsx b/src/panelWebView/components/TagPicker.tsx
index 004b4475..8eec3679 100644
--- a/src/panelWebView/components/TagPicker.tsx
+++ b/src/panelWebView/components/TagPicker.tsx
@@ -15,6 +15,7 @@ import { PanelSettingsAtom } from '../state';
 import { SparklesIcon } from '@heroicons/react/outline';
 import * as l10n from '@vscode/l10n';
 import { LocalizationKey } from '../../localization';
+import useDropdownStyle from '../hooks/useDropdownStyle';
 
 export interface ITagPickerProps {
   type: TagType;
@@ -58,6 +59,7 @@ const TagPicker: React.FunctionComponent<ITagPickerProps> = ({
   const [inputValue, setInputValue] = React.useState<string>('');
   const prevSelected = usePrevious(crntSelected);
   const inputRef = React.useRef<HTMLInputElement | null>(null);
+  const { getDropdownStyle } = useDropdownStyle(inputRef as any);
   const dsRef = React.useRef<Downshift<string> | null>(null);
   const settings = useRecoilValue(PanelSettingsAtom);
   const [loading, setLoading] = React.useState<boolean>(false);
@@ -277,38 +279,6 @@ const TagPicker: React.FunctionComponent<ITagPickerProps> = ({
     );
   }, [settings?.aiEnabled, label, type]);
 
-  const dropdownStyle = useCallback((isOpen) => {
-    if (isOpen && inputRef.current) {
-      const wrapper = inputRef.current.closest(".collapsible__body");
-      const dropdown = inputRef.current.parentElement?.parentElement?.querySelector('.article__tags__dropbox');
-
-      if (!wrapper || !dropdown) {
-        return undefined;
-      }
-
-      const wrapperStyles = getComputedStyle(wrapper);
-      const padding = parseInt(wrapperStyles.paddingTop) + parseInt(wrapperStyles.paddingBottom);
-      const wrapperHeight = wrapper.clientHeight - padding;
-
-      const tagPickerElm = inputRef.current.parentElement?.parentElement;
-      const dropdownHeight = dropdown?.clientHeight;
-
-      if (!tagPickerElm || !dropdownHeight) {
-        return undefined;
-      }
-
-      const tagPickerTop = tagPickerElm.offsetTop;
-
-      const fullHeight = tagPickerTop + dropdownHeight;
-
-      if (fullHeight > wrapperHeight) {
-        return "calc(100% - 38px)";
-      }
-    }
-
-    return undefined;
-  }, [inputRef]);
-
   useEffect(() => {
     setTimeout(() => {
       triggerFocus();
@@ -322,7 +292,7 @@ const TagPicker: React.FunctionComponent<ITagPickerProps> = ({
   }, [crntSelected]);
 
   return (
-    <div className={`article__tags`}>
+    <div className={`article__tags metadata_field`}>
       {
         loading && (
           <div className='metadata_field__loading'>
@@ -405,19 +375,19 @@ const TagPicker: React.FunctionComponent<ITagPickerProps> = ({
             </div>
 
             <ul
-              className={`article__tags__dropbox ${isOpen ? 'open' : 'closed'}`}
+              className={`field_dropdown article__tags__dropbox ${isOpen ? 'open' : 'closed'}`}
               style={{
-                bottom: dropdownStyle(isOpen)
+                bottom: getDropdownStyle(isOpen)
               }}
               {...getMenuProps()}
             >
-              {isOpen
-                ? options
+              {
+                options
                   .filter((option) => filterList(option, inputValue))
                   .map((item, index) => (
                     <li {...getItemProps({ key: item, index, item })}>{item}</li>
                   ))
-                : null}
+              }
             </ul>
           </>
         )}
diff --git a/src/panelWebView/hooks/useDropdownStyle.tsx b/src/panelWebView/hooks/useDropdownStyle.tsx
new file mode 100644
index 00000000..ff924f63
--- /dev/null
+++ b/src/panelWebView/hooks/useDropdownStyle.tsx
@@ -0,0 +1,53 @@
+import { useCallback } from 'react';
+
+export default function useDropdownStyle(inputRef: React.MutableRefObject<HTMLInputElement | null>) {
+  const bottomStyle = "calc(100% - 38px)";
+  const listItemHeight = 28;
+
+  const getDropdownStyle = useCallback((isOpen) => {
+    if (isOpen && inputRef.current) {
+      const wrapper = inputRef.current.closest(".collapsible__body");
+      const dropdown = inputRef.current.parentElement?.parentElement?.querySelector('.field_dropdown');
+
+      if (!wrapper || !dropdown) {
+        return undefined;
+      }
+
+      const wrapperStyles = getComputedStyle(wrapper);
+      const padding = parseInt(wrapperStyles.paddingTop) + parseInt(wrapperStyles.paddingBottom);
+      const wrapperHeight = wrapper.clientHeight - padding;
+
+      const dropdownElm: HTMLElement | null = inputRef.current.closest(".metadata_field");
+      const hasStyles = dropdown.getAttribute("style")?.includes(bottomStyle);
+
+      if (hasStyles) {
+        return bottomStyle;
+      }
+
+      let dropdownHeight = dropdown?.clientHeight;
+      if (dropdownHeight === 0) {
+        const listItems = dropdown?.querySelectorAll('li');
+        if (listItems && listItems.length > 0) {
+          dropdownHeight = listItems.length * listItemHeight;
+        }
+      }
+
+      if (!dropdownElm || !dropdownHeight) {
+        return undefined;
+      }
+
+      const tagPickerTop = dropdownElm.offsetTop;
+
+      const fullHeight = tagPickerTop + dropdownHeight;
+      if (fullHeight > wrapperHeight) {
+        return bottomStyle;
+      }
+    }
+
+    return undefined;
+  }, [inputRef]);
+
+  return {
+    getDropdownStyle
+  };
+}
\ No newline at end of file
diff --git a/src/panelWebView/styles.css b/src/panelWebView/styles.css
index d1203b9a..e90a513b 100644
--- a/src/panelWebView/styles.css
+++ b/src/panelWebView/styles.css
@@ -8,6 +8,26 @@
   }
 }
 
+@keyframes vscode-loader {
+  0% {
+    left: 0;
+    width: 30px;
+  }
+  25% {
+    width: 50px;
+  }
+  50% {
+    width: 20px;
+  }
+  75% {
+    width: 50px;
+  }
+  100% {
+    width: 20px;
+    left: 100%;
+  }
+}
+
 /* Overrides */
 vscode-button,
 button {
@@ -776,6 +796,11 @@ vscode-divider {
   padding: 0.5rem;
 }
 
+/* Dropdown */
+.field_dropdown.closed {
+  display: none;
+}
+
 /* Tags */
 .article__tags {
   position: relative;
@@ -1117,3 +1142,33 @@ vscode-divider {
   text-align: center;
   padding: 1rem 1.25rem;
 }
+
+/* VSCode loader */
+.vscode__loader {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  width: 100%;
+  height: 100%;
+  background-color: var(--vscode-sideBar-background);
+  opacity: 75%;
+  z-index: 50;
+
+  .vscode__loader__bar {
+    position: absolute;
+    top: 0;
+    width: 100%;
+    height: 2px;
+
+    .vscode__loader__bar__animation {
+      height: 100%;
+      position: absolute;
+      border-radius: 2px;
+      background-color: var(--vscode-activityBarBadge-background);
+
+      animation: vscode-loader 4s ease-in-out infinite;
+    }
+  }
+}
diff --git a/src/parsers/ParserEngines.ts b/src/parsers/ParserEngines.ts
index 9288f2a9..91938ab8 100644
--- a/src/parsers/ParserEngines.ts
+++ b/src/parsers/ParserEngines.ts
@@ -1,5 +1,4 @@
 import * as yaml from 'yaml';
-import * as jsyaml from 'js-yaml';
 import * as toml from '@iarna/toml';
 import { Format, FrontMatterParser } from '.';
 
@@ -46,7 +45,16 @@ export const Engines = {
       parse: (value: string) => {
         return yaml.parse(removeCarriageReturn(value));
       },
-      stringify: (obj: any, options?: any) => {
+      stringify: (
+        obj: any,
+        options?: {
+          indent?: number;
+          noArrayIndent?: boolean;
+          skipInvalid?: true;
+          noCompatMode?: true;
+          lineWidth?: number;
+        }
+      ) => {
         // Do our own parsing to keep the comments
         if (FrontMatterParser.currentContent) {
           const originalContent = FrontMatterParser.currentContent;
@@ -76,9 +84,11 @@ export const Engines = {
             let updatedValue = docYaml.toJSON();
 
             return yaml.stringify(updatedValue, {
-              lineWidth: 5000,
+              lineWidth: options?.lineWidth || 5000,
               defaultStringType: 'PLAIN',
-              keepUndefined: false
+              keepUndefined: false,
+              indent: options?.indent || 2,
+              indentSeq: options?.noArrayIndent ? false : true
             });
           }
         }
diff --git a/src/services/PagesParser.ts b/src/services/PagesParser.ts
index 88caa5e3..2d421c54 100644
--- a/src/services/PagesParser.ts
+++ b/src/services/PagesParser.ts
@@ -18,6 +18,7 @@ import {
   ContentType,
   DateHelper,
   Extension,
+  FilesHelper,
   isValidFile,
   Logger,
   Notifications,
@@ -207,6 +208,7 @@ export class PagesParser {
         // FrontMatter properties
         fmFolder: folderTitle,
         fmFilePath: filePath,
+        fmRelFileWsPath: FilesHelper.absToRelPath(filePath),
         fmRelFilePath: parseWinPath(filePath).replace(wsFolder?.fsPath || '', ''),
         fmFileName: fileName,
         fmDraft: ContentType.getDraftStatus(article?.data),
@@ -236,21 +238,32 @@ export class PagesParser {
           previewFieldParents = ['preview'];
         }
       }
+      // Retrieve the tags from the artilce
+      let tagParents = ContentType.findFieldsByTypeDeep(contentType.fields, 'tags');
+      if (tagParents.length > 0) {
+        const firstField = tagParents[0];
+        if (firstField.length > 0) {
+          const tagsValue = ContentType.getFieldValue(
+            article.data,
+            firstField.map((f) => f.name)
+          );
+          page.fmTags = typeof tagsValue === 'string' ? tagsValue.split(',') : tagsValue;
+        }
+      }
 
-      let tagParents = ContentType.findFieldByType(contentType.fields, 'tags');
-      const tagsValue = ContentType.getFieldValue(
-        article.data,
-        tagParents.length !== 0 ? tagParents : ['tags']
-      );
-      page.fmTags = typeof tagsValue === 'string' ? tagsValue.split(',') : tagsValue;
-
-      let categoryParents = ContentType.findFieldByType(contentType.fields, 'categories');
-      const categoriesValue = ContentType.getFieldValue(
-        article.data,
-        categoryParents.length !== 0 ? categoryParents : ['categories']
-      );
-      page.fmCategories =
-        typeof categoriesValue === 'string' ? categoriesValue.split(',') : categoriesValue;
+      // Retrieve the categories from the artilce
+      let categoryParents = ContentType.findFieldsByTypeDeep(contentType.fields, 'categories');
+      if (categoryParents.length > 0) {
+        const firstField = categoryParents[0];
+        if (firstField.length > 0) {
+          const categoriesValue = ContentType.getFieldValue(
+            article.data,
+            firstField.map((f) => f.name)
+          );
+          page.fmCategories =
+            typeof categoriesValue === 'string' ? categoriesValue.split(',') : categoriesValue;
+        }
+      }
 
       // Check if parent fields were retrieved, if not there was no image present
       if (previewFieldParents.length > 0) {
diff --git a/src/services/PinnedItems.ts b/src/services/PinnedItems.ts
new file mode 100644
index 00000000..88018b1f
--- /dev/null
+++ b/src/services/PinnedItems.ts
@@ -0,0 +1,111 @@
+import { Config, JsonDB } from 'node-json-db';
+import { Folders } from '../commands';
+import { join } from 'path';
+import { LocalStore } from '../constants';
+import { FilesHelper, parseWinPath } from '../helpers';
+
+const PINNED_DB = '/pinned';
+
+export class PinnedItems {
+  /**
+   * Retrieve all the pinned items
+   * @returns
+   */
+  public static async get() {
+    const db = PinnedItems.getPinnedDb();
+    if (!db) {
+      return undefined;
+    }
+
+    let allPinned: string[] = [];
+    if (await db.exists(PINNED_DB)) {
+      allPinned = (await db.getObject(PINNED_DB)) as string[];
+    }
+
+    return allPinned;
+  }
+
+  /**
+   * Pin an item
+   * @param path
+   */
+  public static async pin(path: string) {
+    if (!path) {
+      return;
+    }
+
+    const relPath = FilesHelper.absToRelPath(path);
+    if (!relPath) {
+      return;
+    }
+
+    const db = PinnedItems.getPinnedDb();
+    if (!db) {
+      return;
+    }
+
+    let allPinned: string[] = [];
+    if (await db.exists(PINNED_DB)) {
+      allPinned = (await db.getObject(PINNED_DB)) as string[];
+    }
+
+    allPinned.push(relPath);
+    allPinned = [...new Set(allPinned)];
+
+    await db.push(PINNED_DB, allPinned, true);
+
+    return allPinned;
+  }
+
+  /**
+   * Remove a pinned item
+   * @param path
+   * @returns
+   */
+  public static async remove(path: string) {
+    if (!path) {
+      return;
+    }
+
+    const relPath = FilesHelper.absToRelPath(path);
+    if (!relPath) {
+      return;
+    }
+
+    const db = PinnedItems.getPinnedDb();
+    if (!db) {
+      return;
+    }
+
+    let allPinned: string[] = [];
+    if (await db.exists(PINNED_DB)) {
+      allPinned = (await db.getObject(PINNED_DB)) as string[];
+    }
+
+    allPinned = allPinned.filter((p) => p !== relPath);
+
+    await db.push(PINNED_DB, allPinned, true);
+
+    return allPinned;
+  }
+
+  /**
+   * Retrieve the pinned database
+   * @returns
+   */
+  private static getPinnedDb() {
+    const wsFolder = Folders.getWorkspaceFolder();
+    if (!wsFolder) {
+      return;
+    }
+
+    const dbFolder = join(
+      parseWinPath(wsFolder?.fsPath || ''),
+      LocalStore.rootFolder,
+      LocalStore.databaseFolder
+    );
+    const dbPath = join(dbFolder, LocalStore.pinnedItemsDatabaseFile);
+
+    return new JsonDB(new Config(dbPath, true, false, '/'));
+  }
+}
diff --git a/src/services/Terminal.ts b/src/services/Terminal.ts
new file mode 100644
index 00000000..a84d55fd
--- /dev/null
+++ b/src/services/Terminal.ts
@@ -0,0 +1,66 @@
+import { workspace } from 'vscode';
+import * as os from 'os';
+
+interface ShellSetting {
+  path: string;
+}
+
+export class Terminal {
+  /**
+   * Return the shell path for the current platform
+   */
+  public static get shell() {
+    const shell: string | { path: string } | undefined = Terminal.getShellPath();
+    let shellPath: string | undefined = undefined;
+
+    if (typeof shell !== 'string' && !!shell) {
+      shellPath = shell.path;
+    } else {
+      shellPath = shell || undefined;
+    }
+
+    return shellPath;
+  }
+
+  /**
+   * Retrieve the automation profile for the current platform
+   * @returns
+   */
+  private static getShellPath(): string | ShellSetting | undefined {
+    const platform = Terminal.getPlatform();
+    const terminalSettings = workspace.getConfiguration('terminal');
+
+    const automationProfile = terminalSettings.get<string | ShellSetting>(
+      `integrated.automationProfile.${platform}`
+    );
+    if (!!automationProfile) {
+      return automationProfile;
+    }
+
+    const defaultProfile = terminalSettings.get<string>(`integrated.defaultProfile.${platform}`);
+    const profiles = terminalSettings.get<{ [prop: string]: ShellSetting }>(
+      `integrated.profiles.${platform}`
+    );
+
+    if (defaultProfile && profiles && profiles[defaultProfile]) {
+      return profiles[defaultProfile];
+    }
+
+    return terminalSettings.get(`integrated.shell.${platform}`);
+  }
+
+  /**
+   * Get the current platform
+   * @returns
+   */
+  private static getPlatform = (): 'windows' | 'linux' | 'osx' => {
+    const platform = os.platform();
+    if (platform === 'win32') {
+      return 'windows';
+    } else if (platform === 'darwin') {
+      return 'osx';
+    }
+
+    return 'linux';
+  };
+}
diff --git a/src/services/index.ts b/src/services/index.ts
new file mode 100644
index 00000000..2e13bb82
--- /dev/null
+++ b/src/services/index.ts
@@ -0,0 +1,6 @@
+export * from './Credentials';
+export * from './ModeSwitch';
+export * from './PagesParser';
+export * from './PinnedItems';
+export * from './SponsorAI';
+export * from './Terminal';
diff --git a/src/utils/flattenObjectKeys.ts b/src/utils/flattenObjectKeys.ts
new file mode 100644
index 00000000..0e129c62
--- /dev/null
+++ b/src/utils/flattenObjectKeys.ts
@@ -0,0 +1,32 @@
+import { join } from 'path';
+
+export const flattenObjectKeys = (obj: any, crntKey: string = '') => {
+  let toReturn: string[] = [];
+  const keys = Object.keys(obj);
+
+  for (const key of keys) {
+    const crntObj = obj[key];
+
+    if (typeof crntObj === 'object' && crntObj !== null && Object.keys(crntObj).length > 0) {
+      const hasTextKeys = Object.keys(crntObj).some((subKey) => {
+        if (typeof crntObj[subKey] === 'string') {
+          return true;
+        }
+
+        return false;
+      });
+
+      if (hasTextKeys) {
+        toReturn.push(join(crntKey, key));
+        continue;
+      }
+
+      const flatKeyNames = flattenObjectKeys(crntObj, join(crntKey, key));
+      toReturn = [...toReturn, ...flatKeyNames];
+    } else if (typeof crntObj !== 'string' || Object.keys(crntObj).length === 0) {
+      toReturn.push(join(crntKey, key));
+    }
+  }
+
+  return [...new Set(toReturn)];
+};
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 806cacd1..457cc140 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -3,6 +3,8 @@ export * from './encodeEmoji';
 export * from './existsAsync';
 export * from './fetchWithTimeout';
 export * from './fieldWhenClause';
+export * from './flattenObjectKeys';
+export * from './getLocalizationFile';
 export * from './mkdirAsync';
 export * from './readFileAsync';
 export * from './readdirAsync';
diff --git a/ssg-scripts/astro.collections.mjs b/ssg-scripts/astro.collections.mjs
new file mode 100644
index 00000000..7603d2f8
--- /dev/null
+++ b/ssg-scripts/astro.collections.mjs
@@ -0,0 +1,221 @@
+import { writeFileSync } from "fs";
+import { join } from "path";
+import { createServer } from "vite";
+import zod from "zod";
+
+const {
+  ZodDefault,
+  ZodObject,
+  ZodOptional,
+  ZodString,
+  ZodEffects,
+  ZodEnum
+} = zod;
+
+/**
+ * Process the Zod field
+ * @param {ZodTypeAny} field 
+ * @param {string} defaultValue 
+ * @returns 
+ */
+function getField(field, defaultValue = undefined) {
+  let isOptional = false;
+
+  // Handle various type transformations and assignments
+  if (field instanceof ZodOptional) {
+    isOptional = true;
+    const type = field.unwrap();
+
+    return getField(type, isOptional, defaultValue)
+  }
+
+  if (field instanceof ZodDefault) {
+    // https://github.com/colinhacks/zod/blob/master/README.md#default
+    isOptional = true;
+    defaultValue = field.parse(undefined);
+    // https://github.com/sachinraja/zod-to-ts/blob/main/src/index.ts
+    const type = field._def.innerType;
+    return getField(type, isOptional, defaultValue)
+  }
+
+  return {
+    type: field,
+    isOptional,
+    defaultValue
+  }
+}
+
+/**
+ * Generate the field information
+ * @param {string} name 
+ * @param {ZodTypeAny} type 
+ * @returns 
+ */
+function generateFieldInfo(name, type) {
+  let description = type.description;
+  let defaultValue = undefined;
+
+  const { 
+    type: fieldType, 
+    isOptional: isFieldOptional, 
+    defaultValue: fieldDefaultValue 
+  } = getField(type, defaultValue);
+
+  const fieldInfo = {
+    name: name,
+    description: description,
+    defaultValue: fieldDefaultValue,
+    type: fieldType._def.typeName,
+    required: !isFieldOptional,
+  };
+
+  if (fieldType instanceof ZodObject) {
+    const subFields = extractFieldInfoFromShape(fieldType);
+    
+    fieldInfo.fields = subFields;
+  }
+
+  if (fieldType instanceof ZodEffects) {
+    fieldInfo.type = fieldType.sourceType().fmFieldType;
+  }
+
+  if (fieldType instanceof ZodEnum) {
+    fieldInfo.options = fieldType.options;
+  }
+
+  if (fieldType instanceof ZodString) {
+    // https://github.com/StefanTerdell/zod-to-json-schema/blob/master/src/parsers/string.ts#L45
+    if (fieldType._def.checks && fieldType._def.checks.length > 0) {
+      const check = fieldType._def.checks.pop();
+      fieldInfo.type = check.kind;
+    }
+  }
+
+  return fieldInfo;
+}
+
+/**
+ * Parse the scheme into an array of fields
+ * @param {ZodTypeAny} type 
+ * @returns 
+ */
+function extractFieldInfoFromShape(type) {
+  if (type instanceof ZodOptional) {
+    type = type.unwrap();
+  }
+
+  if (!(type instanceof ZodObject)) {
+    // Return an empty array if the type is not of the expected type
+    return []; 
+  }
+
+  // Iterate through the shape properties
+  // https://github.com/sachinraja/zod-to-ts/blob/1389b33557bcca8a02da66cd5c48efbe7579720c/src/index.ts#L134
+  const properties = Object.entries(type._def.shape());
+  const fieldInfoList = properties.map(([fieldName, fieldShape]) => {
+    return generateFieldInfo(fieldName, fieldShape);
+  });
+
+  return fieldInfoList;
+}
+
+/**
+ * Process each content collection
+ * @param {*} collections 
+ * @returns 
+ */
+function processCollection(collections) {
+  if (!Array.isArray(collections)) {
+    return [];
+  }
+
+  return collections.map(([name, collection]) => {
+    const schema = typeof collection.schema === "function" ? collection.schema({
+      image() {
+        const field = zod.string();
+        field.fmFieldType = "image";
+        return field;
+      }
+    }) : collection.schema;
+
+    return {
+      name,
+      type: collection.type || "content",
+      fields: extractFieldInfoFromShape(schema),
+    };
+  });
+}
+
+/**
+ * More info: https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention
+ * @returns 
+ */
+const astroContentModulePlugin = () => {
+  const astroContent = "astro:content";
+  const astroContentMarker = `\0${astroContent}`;
+
+  return {
+    name: "astro-content-collections",
+    resolveId(importee) {
+      if (importee === astroContent) {
+        return astroContentMarker;
+      }
+    },
+    load(id) {
+      if (id === astroContentMarker) {
+        // https://github.com/withastro/astro/blob/defab70cb2a0c67d5e9153542490d2749046b151/packages/astro/content-module.template.mjs#L12
+        return `
+          export { z } from 'astro/zod';
+          // Reference: /node_modules/astro/content-module.template.mjs
+          export function defineCollection(config) {
+            if (!config.type) config.type = 'content';
+            return config;
+          };
+        `;
+      }
+    }
+  }
+};
+
+/**
+ * Start of the Astro Collections script
+ */
+(async () => {
+  const configPath = process.argv[2];
+  if (!configPath || typeof configPath !== "string") {
+    console.log("No config path provided");
+    process.exit(1);
+  }
+
+  // https://vitejs.dev/guide/ssr.html#setting-up-the-dev-server
+  // https://github.com/withastro/astro/blob/defab70cb2a0c67d5e9153542490d2749046b151/packages/astro/src/core/config/vite-load.ts#L8
+  const server = await createServer({
+    server: {
+      middlewareMode: true,
+      hmr: false
+    },
+    optimizeDeps: {
+      disabled: true,
+    },
+    appType: "custom",
+    plugins: [astroContentModulePlugin()]
+  });
+
+  try {
+    // https://github.dev/withastro/astro/blob/defab70cb2a0c67d5e9153542490d2749046b151/packages/astro/src/content/utils.ts#L334
+    const contentModule = await server.ssrLoadModule(configPath)
+
+    const collections = Object.entries(contentModule.collections ?? {});
+    const processedCollections = processCollection(collections);
+
+    writeFileSync(join(process.cwd(), `./.frontmatter/temp/astro.collections.json`), JSON.stringify(processedCollections));
+    
+    console.log("Collections generated successfully");
+    process.exit(0);
+  } catch (error) {
+    console.log(error.message);
+    process.exit(1);
+  } finally {
+    await server.close();
+  }
+})();
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
index 0b5d0d8b..1addc4f6 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -14,6 +14,13 @@ module.exports = {
           from: {
             transform: 'rotate(360deg)'
           },
+        },
+        'vscode-loader': {
+          '0%': { left: '0', width: '30px' },
+          '25%': { width: '50px' },
+          '50%': { width: '20px' },
+          '75%': { width: '50px' },
+          '100%': { width: '20px', left: '100%' }
         }
       },
       colors: {
diff --git a/webpack/extension.config.js b/webpack/extension.config.js
index ea2617af..1c5b0c3d 100644
--- a/webpack/extension.config.js
+++ b/webpack/extension.config.js
@@ -4,6 +4,7 @@
 
 const path = require('path');
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
+const IgnoreDynamicRequire = require('webpack-ignore-dynamic-require');
 
 const config = [
   {
@@ -56,7 +57,9 @@ const config = [
         }
       }
     },
-    plugins: []
+    plugins: [
+      new IgnoreDynamicRequire()
+    ]
   }
 ];