<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">

<channel data-v-component-posts="feed" data-v-limit="50" data-v-type="post" data-v-direction="desc" data-v-order_by="updated_at">	<title>News Vvveb</title>
	<link>https://vvveb.com/feed/posts</link>
	<description>The latest news about Vvveb</description>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://vvveb.com</generator>

	<image>
		<url>/favicon.ico</url>
		<title>Vvveb News</title>
		<link>https://www.vvveb.com/feed/posts</link>
		<width>32</width>
		<height>32</height>
	</image> 

		<item data-v-post="post" data-v-id="275">
			<title data-v-post-name="name">Sidebar</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/_Sidebar</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 27 Mar 2026 21:03:40 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Overview 
Components 
Inputs 
Sections 
Events]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<br/>
<br/>
<p align="center"><img src="https://www.vvveb.com/admin/default/img/biglogo.png" alt="VvvebJs" align="center"/></p>
<br/>
<br/>
<ul>
<li><a href="./Home">Overview</a></li>
<li><a href="./Components">Components</a></li>
<li><a href="./Inputs">Inputs</a></li>
<li><a href="./Sections">Sections</a></li>
<li><a href="./Events">Events</a></li>
</ul>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="276">
			<title data-v-post-name="name">Sections</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/Sections</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 27 Mar 2026 21:03:40 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Overview 
Sections are predefined horizontal page &quot;slices&quot; that can be inserted in the page. 
To add a section you need to use Vvveb.Sections.add method, the first parameter is the unique se]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<h2>Overview</h2>
<p>Sections are predefined horizontal page &quot;slices&quot; that can be inserted in the page.</p>
<p>To add a section you need to use <code>Vvveb.Sections.add</code> method, the first parameter is the unique section name.</p>
<p>The second parameter is an object with the following keys</p>
<ul>
<li>name</li>
<li>image</li>
<li>html</li>
</ul>
<p>Example:</p>
<pre><code class="language-js">Vvveb.Sections.add(&quot;bootstrap5/my-section&quot;, {
    name: &quot;My custom section&quot;,
    image: &quot;https://assets.startbootstrap.com/img/screenshots/snippets/sign-in-split.jpg&quot;, //screenshot
    html: `
&lt;section data-name=&quot;sigin-split&quot;&gt;    
&lt;div class=&quot;container-fluid&quot;&gt;
  &lt;div class=&quot;row no-gutter&quot;&gt;
	&lt;h1&gt;My section&lt;/h1&gt;
  &lt;/div&gt;  
&lt;/div&gt;  
`,
});    
</code></pre>
<p>A good practice is to have the section html wrapped in a <code>&lt;section&gt;</code> tag, you can also use <code>&lt;header&gt;</code> or <code>&lt;footer&gt;</code>.</p>
<p>Based on this tag the editor will insert the section either at the end of the page for <code>&lt;section&gt;</code> or at the top for <code>&lt;header&gt;</code> and for <code>&lt;footer&gt;</code> after the existing <code>&lt;footer&gt;</code> if there is one already added in the page.</p>
<h2>Section group</h2>
<p>For a section to be visible in the left panel it needs to be added to a section group, you can do this by including it in the <code>Vvveb.SectionsGroup</code> array using the group name as a key.</p>
<p>For example Bootstrap section group has the following definition.</p>
<pre><code class="language-js">Vvveb.SectionsGroup['Bootstrap'] = [
  &quot;bootstrap5/signin-split&quot;,  
  &quot;bootstrap5/image-gallery&quot;, 
  &quot;bootstrap5/video-header&quot;, 
  &quot;bootstrap5/slider-header&quot;
];
</code></pre>
<h2>Automatic generation from html files</h2>
<p>Because sections are mostly html code it's easier to maintain them as html files grouped in folders and generate the <code>sections.js</code> file to be included in VvvebJs when changing or adding new sections.</p>
<p>This approach is used in the bundled <a href="https://github.com/givanz/landing">Landing theme</a> where sections are grouped in folders <a href="https://github.com/givanz/landing/tree/main/src/sections">https://github.com/givanz/landing/tree/main/src/sections</a></p>
<p>In the theme folder <code>/demo/landing</code> run the following commands to (re)generate sections.</p>
<h3>Generate html files</h3>
<pre><code class="language-bash">npm run gulp
</code></pre>
<h3>Watch for changes for development</h3>
<pre><code class="language-bash">npm run gulp watch
</code></pre>
<h3>Generate sections list for VvvebJs page builder</h3>
<pre><code class="language-bash">npm run gulp sections
</code></pre>
<p>This will generate <code>demo/landing/sections/sections.js</code> file that is included in VvvebJs</p>
<h3>Generate blocks list for VvvebJs editor</h3>
<pre><code class="language-bash">npm run gulp blocks
</code></pre>
<h3>Generate screenshots for sections</h3>
<pre><code class="language-bash">npm run gulp screenshots
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="277">
			<title data-v-post-name="name">Events</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/Events</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 27 Mar 2026 21:03:40 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Events 
Editor 
propertyChange 
Called by a input object when the property changes, the editor will listen to this event to update the element when a property changes. 
Inputs trigger this event using]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<h2>Events</h2>
<h2>Editor</h2>
<h3>propertyChange</h3>
<p>Called by a input object when the property changes, the editor will listen to this event to update the element when a property changes.</p>
<p>Inputs trigger this event using</p>
<pre><code class="language-javascript">new CustomEvent('propertyChange', { detail: {value, input, origEvent} });
</code></pre>
<h3>vvveb.iframe.loaded</h3>
<p>The editor triggers this event after the page/iframe is loaded and the the editor finished setting up the page.</p>
<p>The detail parameter is set to iframe document object.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.iframe.loaded&quot;, {detail: self.frameDoc}));
</code></pre>
<h3>vvveb.getHtml.before</h3>
<p>This event is triggered by the Vvveb.Builder.getHtml method before removing helpers and other processing.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.getHtml.before&quot;, {detail: document});
</code></pre>
<p>Example use by aos plugin to remove classes before page save</p>
<pre><code class="language-javascript">//clean aos classes on save
window.addEventListener(&quot;vvveb.getHtml.before&quot;, function(event) {
	let doc = event.detail;
	doc.querySelectorAll(&quot;[data-aos]&quot;).forEach(e =&gt; e.classList.remove(&quot;aos-animate&quot;, &quot;aos-init&quot;));
});
</code></pre>
<h3>vvveb.getHtml.after</h3>
<p>This event is triggered by the Vvveb.Builder.getHtml method finished processing the html.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.getHtml.after&quot;, {detail: doc}));
</code></pre>
<p>Example use by aos plugin to add back classes after page save</p>
<pre><code class="language-javascript">window.addEventListener(&quot;vvveb.getHtml.after&quot;, function(event) {
	let doc = event.detail;
	doc.querySelectorAll(&quot;[data-aos]&quot;).forEach(e =&gt; e.classList.add(&quot;aos-animate&quot;, &quot;aos-init&quot;));
});		 
</code></pre>
<h3>vvveb.getHtml.filter</h3>
<p>Similar with vvveb.getHtml.after but passes html code instead of document object, used for processing html code instead of manipulating the document.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.getHtml.filter&quot;, {detail: html}));
</code></pre>
<h3>vvveb.ModalCodeEditor.save</h3>
<p>Called by the code editor modal with <code>detail</code> set as the value of the editor content.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.ModalCodeEditor.save&quot;, {detail: value}));
</code></pre>
<h3>vvveb.FileManager.deletePage</h3>
<p>Called when a page is deleted from file manager, <code>detail</code> parameter is set to page object</p>
<p>Page object structure <code>{name, title,  url, file}</code></p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.FileManager.deletePage&quot;, {detail: page})
</code></pre>
<h3>vvveb.FileManager.renamePage</h3>
<p>Called when a page is renamed from file manager, <code>detail</code> parameter is set to page object and new file name.</p>
<p>Page object structure <code>{name, title,  url, file}</code></p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.FileManager.renamePage&quot;, {detail: {page, newfile}});
</code></pre>
<h3>vvveb.FileManager.addPage</h3>
<p>Called when a new page is added to file manager.</p>
<p>Detail parameter contains an array with page name and page object.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.FileManager.addPage&quot;, {detail: [name, data]})
</code></pre>
<h3>vvveb.FileManager.loadPage</h3>
<p>Called when a page is loaded.</p>
<p>Detail parameter contains the page object.</p>
<pre><code class="language-javascript">new CustomEvent(&quot;vvveb.FileManager.loadPage&quot;, {detail: page})
</code></pre>
<h2>Undo Manager</h2>
<h3>vvveb.undo.add</h3>
<p>Called when a undo action is registered, this happens on a change made to the page</p>
<p>Mutation object has the following structure</p>
<pre><code class="language-javascript">let mutation = {
	type: 'style', //style = css change, attributes = attribute change, characterData = text content change, move = element is moved on the page, childList = new node is added to page
	target: element, 
	attributeName: &quot;color&quot;, 
	oldValue: &quot;red&quot;, 
	newValue: &quot;blue&quot;
}
</code></pre>
<pre><code class="language-javascript">const event = new CustomEvent(&quot;vvveb.undo.add&quot;, {detail: mutation});
</code></pre>
<p>Example used by code editor to update the page html inside the code editor when a change is made to the page</p>
<pre><code class="language-javascript">Vvveb.Builder.frameBody.addEventListener(&quot;vvveb.undo.add&quot;, () =&gt; Vvveb.CodeEditor.setValue());
</code></pre>
<h3>vvveb.undo.restore</h3>
<p>Called when a undo action is restored/reverted</p>
<pre><code class="language-javascript">const event = new CustomEvent(&quot;vvveb.undo.restore&quot;, {detail: mutation});
</code></pre>
<p>Example used by code editor to update the page html inside the code editor when a change is made to the page</p>
<pre><code class="language-javascript">Vvveb.Builder.frameBody.addEventListener(&quot;vvveb.undo.restore&quot;, () =&gt; Vvveb.CodeEditor.setValue());
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="265">
			<title data-v-post-name="name">Component pagination</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/pagination</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 27 Mar 2026 00:03:23 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Pagination is used by components that return multiple pages of results—such as posts, products, comments, orders, or any list‑based component. It automatically generates page links, previous/next ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Pagination is used by components that return multiple pages of results—such as <strong>posts</strong>, <strong>products</strong>, <strong>comments</strong>, <strong>orders</strong>, or any list‑based component. It automatically generates page links, previous/next navigation, and first/last page controls.</p>
<p>To activate pagination, wrap your pagination markup in an element containing:</p>
<pre><code>data-pagination
</code></pre>
<p>This container will automatically receive pagination data from the parent component.</p>
<hr />
<h2><strong>Connecting Pagination to a Component</strong></h2>
<p>Pagination must know <em>which component</em> it belongs to. This is done using the following attributes:</p>
<table class="table">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>data-v-parent-component</strong></td>
<td>Component name (<code>products</code>, <code>posts</code>, <code>comments</code>, etc.)</td>
</tr>
<tr>
<td><strong>data-v-parent-index</strong></td>
<td>Index of the component on the page (useful when multiple components of the same type exist)</td>
</tr>
<tr>
<td><strong>data-v-query-string</strong></td>
<td>Whether to preserve existing URL parameters (<code>true</code>/<code>false</code>)</td>
</tr>
<tr>
<td><strong>data-v-parameters</strong></td>
<td>Extra parameters to include in pagination URLs (JSON object) `</td>
</tr>
</tbody>
</table>
<h3>Example</h3>
<pre><code class="language-html">&lt;div data-pagination
     data-v-parent-component=&quot;products&quot;
     data-v-parent-index=&quot;0&quot;
     data-v-query-string=&quot;true&quot;
     data-v-parameters='{&quot;type&quot;:&quot;post&quot;,&quot;myparam&quot;:&quot;value&quot;}'&gt;
</code></pre>
<p>This ensures the pagination controls update the correct component and preserve or extend URL parameters.</p>
<hr />
<h2><strong>Pagination Data Attributes</strong></h2>
<p>The pagination container receives several dynamic values:</p>
<table class="table">
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>data-count</strong></td>
<td>Total number of pages</td>
</tr>
<tr>
<td><strong>data-current-page</strong></td>
<td>Current page number</td>
</tr>
<tr>
<td><strong>data-current-url</strong></td>
<td>Current page URL</td>
</tr>
</tbody>
</table>
<p>These values can be used to show page indicators, disable buttons, or highlight the active page.</p>
<hr />
<h2><strong>Page Elements</strong></h2>
<p>Pagination uses several repeatable or conditional elements to build navigation.</p>
<h3><strong>Page List Items</strong></h3>
<p>Each page number is wrapped in:</p>
<pre><code>data-page
</code></pre>
<p>Inside it, you can use:</p>
<ul>
<li><strong>data-page-url</strong> — URL for that page</li>
<li><strong>data-page-no</strong> — Page number</li>
</ul>
<p>Example:</p>
<pre><code class="language-html">&lt;li data-page&gt;
  &lt;a data-page-url data-page-no href=&quot;/shop/2&quot;&gt;2&lt;/a&gt;
&lt;/li&gt;
</code></pre>
<hr />
<h3><strong>First Page</strong></h3>
<p>Rendered only when the current page is not the first.</p>
<pre><code class="language-html">&lt;li data-first&gt;
  &lt;a data-page-url&gt;First&lt;/a&gt;
&lt;/li&gt;
</code></pre>
<hr />
<h3><strong>Previous Page</strong></h3>
<p>Rendered only when <code>current_page &gt; 1</code>.</p>
<pre><code class="language-html">&lt;li data-prev&gt;
  &lt;a data-page-url title=&quot;Previous page&quot;&gt;
    &lt;span class=&quot;la la-arrow-left&quot;&gt;&lt;/span&gt;
  &lt;/a&gt;
&lt;/li&gt;
</code></pre>
<hr />
<h3><strong>Next Page</strong></h3>
<p>Rendered only when <code>current_page &lt; pagecount</code>.</p>
<pre><code class="language-html">&lt;li data-next&gt;
  &lt;a data-page-url title=&quot;Next page&quot;&gt;
    &lt;span class=&quot;la la-arrow-right&quot;&gt;&lt;/span&gt;
  &lt;/a&gt;
&lt;/li&gt;
</code></pre>
<hr />
<h3><strong>Last Page</strong></h3>
<p>Rendered only when the current page is not the last.</p>
<pre><code class="language-html">&lt;li data-last&gt;
  &lt;a data-page-url&gt;Last&lt;/a&gt;
&lt;/li&gt;
</code></pre>
<hr />
<h2><strong>Full Pagination Example</strong></h2>
<pre><code class="language-html">&lt;div data-pagination
     data-v-parent-component=&quot;products&quot;
     data-v-parent-index=&quot;0&quot;
     data-v-query-string=&quot;true&quot;
     data-v-parameters=&quot;{}&quot;&gt;

  &lt;nav data-v-if=&quot;pagecount &gt; 1&quot;&gt;
    &lt;ul&gt;

      &lt;!-- Previous --&gt;
      &lt;li class=&quot;page-item pager-prev&quot; data-prev&gt;
        &lt;a data-page-url data-v-if=&quot;current_page &gt; 1&quot; title=&quot;Previous page&quot;&gt;
          &lt;span class=&quot;la la-arrow-left la-lg&quot;&gt;&lt;/span&gt;
        &lt;/a&gt;
      &lt;/li&gt;

      &lt;!-- Page Numbers --&gt;
      &lt;li class=&quot;active&quot; data-page&gt;
        &lt;a data-page-url data-page-no href=&quot;/shop&quot;&gt;1&lt;/a&gt;
      &lt;/li&gt;

      &lt;li data-page&gt;
        &lt;a data-page-url data-page-no href=&quot;/shop/2&quot;&gt;2&lt;/a&gt;
      &lt;/li&gt;

      &lt;li data-page&gt;
        &lt;a data-page-url data-page-no href=&quot;/shop/3&quot;&gt;3&lt;/a&gt;
      &lt;/li&gt;

      &lt;li data-page&gt;
        &lt;a data-page-url data-page-no href=&quot;/shop/4&quot;&gt;4&lt;/a&gt;
      &lt;/li&gt;

      &lt;!-- Next --&gt;
      &lt;li data-next&gt;
        &lt;a data-page-url data-v-if=&quot;current_page &lt; pagecount&quot; title=&quot;Next page&quot;&gt;
          &lt;span class=&quot;la la-arrow-right la-lg&quot;&gt;&lt;/span&gt;
        &lt;/a&gt;
      &lt;/li&gt;

    &lt;/ul&gt;
  &lt;/nav&gt;

&lt;/div&gt;
</code></pre>
<p>This example shows a typical pagination block with previous/next arrows and numbered pages.</p>
<hr />
<h2><strong>How Pagination Works Internally</strong></h2>
<ul>
<li>The parent component (posts, products, comments, etc.) calculates:
<ul>
<li>total items</li>
<li>items per page</li>
<li>total pages</li>
<li>current page</li>
</ul>
</li>
<li>Pagination receives these values and generates:
<ul>
<li>page links</li>
<li>first/prev/next/last controls</li>
<li>URLs with preserved or extended query parameters</li>
</ul>
</li>
<li>When a user clicks a page link, the component reloads with the new page number.</li>
</ul>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="264">
			<title data-v-post-name="name">Component users</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-users</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 27 Mar 2026 00:01:00 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Improve the following documentation for Users component in Vvveb CMS 
The users component displays a list of useristrator users. It supports pagination, filtering, and searching, making it useful for ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<p>Improve the following documentation for Users component in Vvveb CMS</p>

<p>The <strong>users</strong> component displays a list of useristrator users.
It supports pagination, filtering, and searching, making it useful for author listings, team pages, or user management sections within a theme.</p>
<hr />
<h2>Component Options</h2>
<p>Add any option as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>start</strong> - Starting offset for pagination. Useful when manually controlling the list position.</li>
<li><strong>limit</strong> - Number of user users to display per page.</li>
<li><strong>status</strong> - Filter by account status (<code>1</code> for enabled, <code>0</code> for disabled).</li>
<li><strong>search</strong> - Search by username, first name, or last name.</li>
<li><strong>user_id</strong> - Filter by one or more user IDs. Accepts a single value or a comma‑separated list.</li>
</ul>
<p>These options allow you to build flexible user listings, from simple team pages to filtered author directories.</p>
<hr />
<h2>Component Properties</h2>
<p>Each user user is wrapped in an element marked with <code>data-v-user</code>.<br />
Inside each element, the following properties are available:</p>
<ul>
<li><strong>first_name</strong> - <code>data-v-user-first_name</code> - User’s first name.</li>
<li><strong>last_name</strong> - <code>data-v-user-last_name</code> - User’s last name.</li>
<li><strong>avatar_url</strong> - <code>data-v-user-avatar_url</code> - Profile avatar image URL.</li>
<li><strong>cover_url</strong> - <code>data-v-user-cover_url</code> - Cover or background image URL.</li>
<li><strong>url</strong> - <code>data-v-user-url</code> - Public profile page URL.</li>
<li><strong>username</strong> - <code>data-v-user-username</code> - Username used for login.</li>
<li><strong>display_name</strong> - <code>data-v-user-display_name</code> - Public display name.</li>
<li><strong>website</strong> - <code>data-v-user-website</code> - Personal or professional website.</li>
<li><strong>email</strong> - <code>data-v-user-email</code> - Internal email for login and notifications.</li>
<li><strong>public_email</strong> - <code>data-v-user-public_email</code> - Publicly visible email address.</li>
<li><strong>bio</strong> - <code>data-v-user-bio</code> - Short biography or description.</li>
<li><strong>created_at</strong> - <code>data-v-user-created_at</code> - Account creation timestamp.</li>
<li><strong>updated_at</strong> - <code>data-v-user-updated_at</code> - Last update timestamp.</li>
<li><strong>last_ip</strong> - <code>data-v-user-last_ip</code> - Last login IP address.</li>
<li><strong>phone_number</strong> - <code>data-v-user-phone_number</code> - Public phone number (if provided).</li>
</ul>
<p>These properties repeat for each user returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;div data-v-component-users data-v-limit=&quot;4&quot;&gt;

	&lt;div data-v-user&gt;

		&lt;div class=&quot;profile-header&quot;&gt;
			&lt;div class=&quot;cover&quot;&gt;
				&lt;img src=&quot;&quot; data-v-user-cover_url&gt;
			&lt;/div&gt;

			&lt;div class=&quot;avatar&quot;&gt;
				&lt;img data-v-user-avatar_url class=&quot;rounded-circle avatar&quot; alt=&quot;Profile Picture&quot;&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;div class=&quot;px-3 m-3 me-5 d-flex justify-content-between&quot;&gt;
			&lt;div&gt;
				&lt;h1 class=&quot;h3 m-0&quot; data-v-user-display_name&gt;User&lt;/h1&gt;
			&lt;/div&gt;

			&lt;div class=&quot;social-links d-inline-block&quot;&gt;
				&lt;!-- Optional social links --&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;div class=&quot;px-3 m-3 me-5 d-flex&quot;&gt;

			&lt;div&gt;
				&lt;div class=&quot;text-muted&quot;&gt;@&lt;span data-v-user-username&gt;username&lt;/span&gt;&lt;/div&gt;

				&lt;div&gt;
					&lt;a class=&quot;d-block&quot; data-v-user-website href=&quot;#&quot;&gt;
						&lt;span data-v-user-website&gt;example.com&lt;/span&gt;
					&lt;/a&gt;

					&lt;a class=&quot;d-block text-body small&quot; href=&quot;#&quot;&gt;
						&lt;span data-v-user-public_email&gt;user@vvveb.com&lt;/span&gt;
					&lt;/a&gt;

					&lt;a class=&quot;d-block text-body small&quot; href=&quot;#&quot;&gt;
						&lt;span data-v-user-phone_number&gt;123456&lt;/span&gt;
					&lt;/a&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&quot;ms-5&quot;&gt;
				&lt;div data-v-user-bio&gt;My bio&lt;/div&gt;
			&lt;/div&gt;

		&lt;/div&gt;

	&lt;/div&gt;

&lt;/div&gt;
</code></pre>
<p>This example displays a list of up to four user users, each rendered using the available user properties.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="263">
			<title data-v-post-name="name">Component user address</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-user-address</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 27 Mar 2026 00:00:59 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The User Address Component displays a list of customer addresses. It is typically used on the My Account → Addresses page, checkout address selectors, or anywhere a user needs to view, edit, or mana]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>User Address Component</strong> displays a list of customer addresses. It is typically used on the <strong>My Account → Addresses</strong> page, checkout address selectors, or anywhere a user needs to view, edit, or manage saved addresses.</p>
<p>Activate the component by adding:</p>
<pre><code>data-v-component-user-address
</code></pre>
<p>The component automatically loads the addresses of the logged‑in user unless a specific <code>user_id</code> is provided.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>0</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Number of addresses to display</td>
<td><code>4</code></td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-user_id</code></td>
<td>Filter addresses by user ID (useful for admin or multi‑user views)</td>
<td>Logged‑in user</td>
</tr>
</tbody>
</table>
<p>These options allow you to paginate, filter, or override which user’s addresses are displayed.</p>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>Each address is wrapped in:</p>
<pre><code>data-v-user_address
</code></pre>
<p>Inside this element, the following fields are available.</p>
<h3><strong>Address Identity</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>user_address_id</strong></td>
<td><code>data-v-user_address-user_address_id</code></td>
<td>Unique ID of the address</td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-user_address-user_id</code></td>
<td>ID of the user who owns the address</td>
</tr>
<tr>
<td><strong>default_address</strong></td>
<td><code>data-v-user_address-default_address</code></td>
<td><code>1</code> if this is the default address</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Name &amp; Company</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>first_name</strong></td>
<td><code>data-v-user_address-first_name</code></td>
</tr>
<tr>
<td><strong>last_name</strong></td>
<td><code>data-v-user_address-last_name</code></td>
</tr>
<tr>
<td><strong>company</strong></td>
<td><code>data-v-user_address-company</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Address Fields</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>address_1</strong></td>
<td><code>data-v-user_address-address_1</code></td>
</tr>
<tr>
<td><strong>address_2</strong></td>
<td><code>data-v-user_address-address_2</code></td>
</tr>
<tr>
<td><strong>city</strong></td>
<td><code>data-v-user_address-city</code></td>
</tr>
<tr>
<td><strong>post_code</strong></td>
<td><code>data-v-user_address-post_code</code></td>
</tr>
<tr>
<td><strong>country_id</strong></td>
<td><code>data-v-user_address-country_id</code></td>
</tr>
<tr>
<td><strong>region_id</strong></td>
<td><code>data-v-user_address-region_id</code></td>
</tr>
</tbody>
</table>
<p>These fields can be combined to display a formatted address block.</p>
<hr />
<h3><strong>Custom Fields</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>fields</strong></td>
<td><code>data-v-user_address-fields</code></td>
<td>Additional custom fields (if defined in the CMS)</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Actions &amp; URLs</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-user_address-url</code></td>
<td>URL to edit the address</td>
</tr>
<tr>
<td><strong>delete-url</strong></td>
<td><code>data-v-user_address-delete_url</code></td>
<td>URL to delete the address</td>
</tr>
</tbody>
</table>
<p>These URLs are typically used for buttons or links in the address list.</p>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-component-user-address&gt;            
&lt;table&gt;
  &lt;tbody&gt;
	&lt;tr data-v-user_address&gt;
	  &lt;td class=&quot;text-start&quot;&gt;

		&lt;span data-v-user_address-first_name&gt;John&lt;/span&gt;
		&lt;span data-v-user_address-last_name&gt;Doe&lt;/span&gt;
		&lt;br&gt;
		&lt;span data-v-user_address-company&gt;Toyota&lt;/span&gt;
		&lt;br&gt;
		&lt;span data-v-user_address-address_1&gt;Broadway Avenue&lt;/span&gt;
		&lt;span data-v-user_address-address_2&gt;Central Park&lt;/span&gt;
		&lt;span data-v-user_address-city&gt;New york&lt;/span&gt;
		&lt;span data-v-user_address-post_code&gt;1223&lt;/span&gt;

	  &lt;/td&gt;
	  &lt;td class=&quot;text-end align-middle&quot;&gt;
		&lt;a href=&quot;/user/address/edit/1&quot; title=&quot;Edit&quot; class=&quot;btn btn-outline-primary btn-sm border-0&quot; data-v-user_address-url&gt;
		  &lt;i class=&quot;la la-pen&quot;&gt;&lt;/i&gt;
		&lt;/a&gt;
		&lt;a href=&quot;/user/address/delete/1&quot; title=&quot;Delete&quot; class=&quot;btn btn-outline-danger btn-sm border-0&quot; data-v-user_address-delete-url&gt;
		  &lt;i class=&quot;la la-trash&quot;&gt;&lt;/i&gt;
		&lt;/a&gt;
	  &lt;/td&gt;
	&lt;/tr&gt;                              
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</code></pre>
<p>This example displays each saved address with edit and delete actions, making it suitable for a user account dashboard.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="261">
			<title data-v-post-name="name">Graphql schema</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/graphql-schema</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Tue, 10 Mar 2026 20:48:45 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Based on the provided schema, here is the technical documentation for the core entities and types available in the Vvveb CMS GraphQL API. | --- | --- | | product_id | ID | Unique identifier for the pr]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<p>Based on the provided schema, here is the technical documentation for the core entities and types available in the Vvveb CMS GraphQL API.
| --- | --- |
| <code>product_id</code> | <code>ID</code> | Unique identifier for the product.</p>
<p>|
| <code>model</code> | <code>String</code> | Product model identifier.</p>
<p>|
| <code>sku</code> | <code>String</code> | Stock Keeping Unit.</p>
<p>|
| <code>price</code> | <code>Float</code> | The current price of the product.</p>
<p>|
| <code>old_price</code> | <code>Float</code> | The original price (useful for showing discounts).</p>
<p>|
| <code>stock_quantity</code> | <code>Int</code> | Number of items currently in stock.</p>
<p>|
| <code>image</code> | <code>String</code> | Path to the main product image.</p>
<p>|
| <code>weight</code> | <code>Float</code> | Physical weight for shipping calculations.</p>
<p>|
| <code>variants</code> | <code>[ProductVariantType]</code> | Available variations (size, color, etc.).</p>
<p>|
| <code>contents</code> | <code>[ProductContentType]</code> | Localized names and descriptions.</p>
<p>|</p>
<h3>2. Cart (<code>cart</code>)</h3>
<p>Represents a user's active shopping session.</p>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>cart_id</code></td>
<td><code>Id</code></td>
<td>Unique identifier for the cart.</td>
</tr>
</tbody>
</table>
<p>|
| <code>products</code> | <code>[CartProductType]</code> | List of items currently in the cart.</p>
<p>|
| <code>totals</code> | <code>[TotalType]</code> | Breakdown of subtotal, tax, and shipping.</p>
<p>|
| <code>total_price</code> | <code>Float</code> | The grand total amount.</p>
<p>|
| <code>total_formatted</code> | <code>String</code> | Currency-formatted total string.</p>
<p>|
| <code>checkout_url</code> | <code>String</code> | Direct link to the checkout page.</p>
<p>|</p>
<hr />
<h2>📝 Content &amp; Blogging</h2>
<h3>1. Post (<code>post</code>)</h3>
<p>Used for blog articles, news, or generic CMS pages.</p>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>post_id</code></td>
<td><code>ID</code></td>
<td>Unique identifier for the post.</td>
</tr>
</tbody>
</table>
<p>|
| <code>status</code> | <code>String</code> | The post status (e.g., &quot;published&quot;, &quot;draft&quot;).</p>
<p>|
| <code>comment_count</code> | <code>Int</code> | Total number of approved comments.</p>
<p>|
| <code>created_at</code> | <code>String</code> | Timestamp of post creation.</p>
<p>|
| <code>contents</code> | <code>[PostContentType]</code> | Multi-language content (title, body, slug).</p>
<p>|
| <code>seo</code> | <code>[SeoType]</code> | Metadata for search engine optimization.</p>
<p>|</p>
<h3>2. Media (<code>media</code>)</h3>
<p>Represents uploaded assets like images and videos.</p>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>media_id</code></td>
<td><code>ID</code></td>
<td>Unique identifier.</td>
</tr>
</tbody>
</table>
<p>|
| <code>file</code> | <code>String</code> | The file path or URL.</p>
<p>|
| <code>type</code> | <code>String</code> | MIME type or category (image, video, etc.).</p>
<p>|</p>
<hr />
<h2>💳 Orders &amp; Customers</h2>
<h3>Order (<code>order</code>)</h3>
<p>A finalized transaction containing snapshot data of the purchase.</p>
<ul>
<li></li>
</ul>
<p><strong>Identifiers</strong>: Includes <code>order_id</code>, <code>invoice_no</code>, and <code>customer_order_id</code>.</p>
<ul>
<li></li>
</ul>
<p><strong>Customer Info</strong>: Stores <code>first_name</code>, <code>last_name</code>, <code>email</code>, and <code>phone_number</code>.</p>
<ul>
<li></li>
</ul>
<p><strong>Shipping/Billing</strong>: Comprehensive address fields including <code>address_1</code>, <code>city</code>, <code>post_code</code>, and <code>country_id</code>.</p>
<ul>
<li></li>
</ul>
<p><strong>Financials</strong>: Tracks <code>payment_method</code>, <code>shipping_method</code>, <code>total</code>, and <code>currency_id</code>.</p>
<ul>
<li></li>
</ul>
<p><strong>Associations</strong>: Links to <code>products</code>, <code>shipments</code>, <code>subscriptions</code>, and <code>vouchers</code>.</p>
<hr />
<h2>🛠️ System &amp; Configuration</h2>
<ul>
<li></li>
</ul>
<p><strong>Localization</strong>: Supported via <code>language</code> (codes, locales, RTL support) and <code>currency</code> (symbols, decimal places, exchange values).</p>
<ul>
<li></li>
</ul>
<p><strong>Geography</strong>: <code>country</code> data including ISO codes and status.</p>
<ul>
<li></li>
</ul>
<p><strong>Administration</strong>: <code>admin</code> type manages backend users, including <code>role_id</code>, <code>auth_tokens</code>, and <code>failed_logins</code>.</p>
<ul>
<li></li>
</ul>
<p><strong>Marketing</strong>: <code>coupon</code> management (discount types, usage limits, date ranges) and <code>newsletter_list</code> management.</p>
<ul>
<li></li>
</ul>
<p><strong>Customization</strong>: <code>field</code> and <code>field_group</code> allow for extensible data models across posts and products.</p>
<hr />
<h3>Pro Tip: Localized Content</h3>
<p>Most primary entities (Product, Post, Category) do not store names directly. Instead, they use a <code>contents</code> array (e.g., <code>ProductContentType</code>) which maps content to a specific <code>language_id</code>. Always query the <code>contents</code> field to retrieve the correct translation for your frontend.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="217">
			<title data-v-post-name="name">Component admin</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-admin</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sun, 01 Mar 2026 00:01:04 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The admin component displays information about an administrator user. If no admin_id or username is provided, the component automatically shows the currently logged‑in admin user. This makes it usef]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>admin</strong> component displays information about an administrator user.
If no <code>admin_id</code> or <code>username</code> is provided, the component automatically shows the currently logged‑in admin user.
This makes it useful for author profile pages, dashboards, or any template where admin details are needed.</p>
<hr />
<h2>Component Options</h2>
<p>Add any option as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>admin_id</strong> - Loads the admin user with this ID. If set to <code>url</code>, the component will read the <code>admin_id</code> from the URL query string. This is useful for author profile pages where the admin ID is dynamic.</li>
<li><strong>username</strong> - Loads the admin user with this username. If set to <code>url</code>, the component will read the <code>username</code> from the URL query string.</li>
</ul>
<p>Only one of these options is required. If both are omitted, the component displays the currently authenticated admin user.</p>
<hr />
<h2>Component Properties</h2>
<p>The following properties are available inside the component. Each property can be used with its corresponding <code>data-v-admin-*</code> attribute.</p>
<ul>
<li><strong>first_name</strong> - <code>data-v-admin-first_name</code> - Admin’s first name.</li>
<li><strong>last_name</strong> - <code>data-v-admin-last_name</code> - Admin’s last name.</li>
<li><strong>avatar_url</strong> - <code>data-v-admin-avatar_url</code> - URL of the admin’s profile avatar.</li>
<li><strong>cover_url</strong> - <code>data-v-admin-cover_url</code> - URL of the admin’s cover/background image.</li>
<li><strong>url</strong> - <code>data-v-admin-url</code> - Link to the admin’s public profile page.</li>
<li><strong>username</strong> - <code>data-v-admin-username</code> - Admin’s username.</li>
<li><strong>display_name</strong> - <code>data-v-admin-display_name</code> - Public display name.</li>
<li><strong>website</strong> - <code>data-v-admin-website</code> - Personal or professional website.</li>
<li><strong>email</strong> - <code>data-v-admin-email</code> - Internal email used for login and notifications.</li>
<li><strong>public_email</strong> - <code>data-v-admin-public_email</code> - Publicly visible email address.</li>
<li><strong>bio</strong> - <code>data-v-admin-bio</code> - Short biography or description.</li>
<li><strong>created_at</strong> - <code>data-v-admin-created_at</code> - Account creation timestamp.</li>
<li><strong>updated_at</strong> - <code>data-v-admin-updated_at</code> - Last update timestamp.</li>
<li><strong>role_id</strong> - <code>data-v-admin-role_id</code> - Role ID assigned to the admin.</li>
<li><strong>role</strong> - <code>data-v-admin-role</code> - Role name (e.g., Administrator, Editor).</li>
<li><strong>last_ip</strong> - <code>data-v-admin-last_ip</code> - Last login IP address.</li>
<li><strong>phone_number</strong> - <code>data-v-admin-phone_number</code> - Public phone number (if provided).</li>
</ul>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;div data-v-component-admin data-v-admin_id=&quot;url&quot; class=&quot;profile&quot;&gt;

	&lt;div data-v-if=&quot;admin&quot;&gt;

		&lt;div class=&quot;profile-header&quot;&gt;
			&lt;div class=&quot;cover&quot;&gt;
				&lt;img src=&quot;&quot; data-v-admin-cover_url&gt;
			&lt;/div&gt;

			&lt;div class=&quot;avatar&quot;&gt;
				&lt;img data-v-admin-avatar_url class=&quot;rounded-circle avatar&quot; alt=&quot;Profile Picture&quot;&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;div class=&quot;px-3 m-3 me-5 d-flex justify-content-between&quot;&gt;
			&lt;div&gt;
				&lt;h1 class=&quot;h3 m-0&quot; data-v-admin-display_name&gt;User&lt;/h1&gt;
			&lt;/div&gt;

			&lt;div class=&quot;social-links d-inline-block&quot;&gt;
				&lt;!-- Optional social links --&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;div class=&quot;px-3 m-3 me-5 d-flex&quot;&gt;

			&lt;div&gt;
				&lt;div class=&quot;text-muted&quot;&gt;@&lt;span data-v-admin-username&gt;username&lt;/span&gt;&lt;/div&gt;

				&lt;div&gt;
					&lt;a class=&quot;d-block&quot; data-v-admin-website href=&quot;#&quot;&gt;
						&lt;span data-v-admin-website&gt;example.com&lt;/span&gt;
					&lt;/a&gt;

					&lt;a class=&quot;d-block text-body small&quot; href=&quot;#&quot;&gt;
						&lt;span data-v-admin-public_email&gt;admin@vvveb.com&lt;/span&gt;
					&lt;/a&gt;

					&lt;a class=&quot;d-block text-body small&quot; href=&quot;#&quot;&gt;
						&lt;span data-v-admin-phone_number&gt;123456&lt;/span&gt;
					&lt;/a&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&quot;ms-5&quot;&gt;
				&lt;div data-v-admin-bio&gt;My bio&lt;/div&gt;
			&lt;/div&gt;

		&lt;/div&gt;

	&lt;/div&gt;

&lt;/div&gt;
</code></pre>
<p>This example loads the admin profile based on the <code>admin_id</code> found in the URL. All admin details are displayed using the component’s data attributes.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="210">
			<title data-v-post-name="name">Admins Component</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/admins</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Improve the following documentation for Admins component in Vvveb CMS 
The admins component displays a list of administrator users. It supports pagination, filtering, and searching, making it useful f]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<p>Improve the following documentation for Admins component in Vvveb CMS</p>

<p>The <strong>admins</strong> component displays a list of administrator users.
It supports pagination, filtering, and searching, making it useful for author listings, team pages, or admin management sections within a theme.</p>
<h2>Component Properties</h2>
<p>Each admin user is wrapped in an element marked with <code>data-v-admin</code>.<br />
Inside each element, the following properties are available:</p>
<ul>
<li><strong>first_name</strong> — <code>data-v-admin-first_name</code> — Admin’s first name.</li>
<li><strong>last_name</strong> — <code>data-v-admin-last_name</code> — Admin’s last name.</li>
<li><strong>avatar_url</strong> — <code>data-v-admin-avatar_url</code> — Profile avatar image URL.</li>
<li><strong>cover_url</strong> — <code>data-v-admin-cover_url</code> — Cover or background image URL.</li>
<li><strong>url</strong> — <code>data-v-admin-url</code> — Public profile page URL.</li>
<li><strong>username</strong> — <code>data-v-admin-username</code> — Username used for login.</li>
<li><strong>display_name</strong> — <code>data-v-admin-display_name</code> — Public display name.</li>
<li><strong>website</strong> — <code>data-v-admin-website</code> — Personal or professional website.</li>
<li><strong>email</strong> — <code>data-v-admin-email</code> — Internal email for login and notifications.</li>
<li><strong>public_email</strong> — <code>data-v-admin-public_email</code> — Publicly visible email address.</li>
<li><strong>bio</strong> — <code>data-v-admin-bio</code> — Short biography or description.</li>
<li><strong>created_at</strong> — <code>data-v-admin-created_at</code> — Account creation timestamp.</li>
<li><strong>updated_at</strong> — <code>data-v-admin-updated_at</code> — Last update timestamp.</li>
<li><strong>role_id</strong> — <code>data-v-admin-role_id</code> — Role ID assigned to the admin.</li>
<li><strong>role</strong> — <code>data-v-admin-role</code> — Role name (e.g., Administrator, Editor).</li>
<li><strong>last_ip</strong> — <code>data-v-admin-last_ip</code> — Last login IP address.</li>
<li><strong>phone_number</strong> — <code>data-v-admin-phone_number</code> — Public phone number (if provided).</li>
</ul>
<p>These properties repeat for each admin returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;div data-v-component-admins data-v-limit=&amp;quot;4&amp;quot;&amp;gt;

	&amp;lt;div data-v-admin&amp;gt;

		&amp;lt;div class=&amp;quot;profile-header&amp;quot;&amp;gt;
			&amp;lt;div class=&amp;quot;cover&amp;quot;&amp;gt;
				&amp;lt;img src=&amp;quot;&amp;quot; data-v-admin-cover_url&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;avatar&amp;quot;&amp;gt;
				&amp;lt;img data-v-admin-avatar_url class=&amp;quot;rounded-circle avatar&amp;quot; alt=&amp;quot;Profile Picture&amp;quot;&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex justify-content-between&amp;quot;&amp;gt;
			&amp;lt;div&amp;gt;
				&amp;lt;h1 class=&amp;quot;h3 m-0&amp;quot; data-v-admin-display_name&amp;gt;User&amp;lt;/h1&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;social-links d-inline-block&amp;quot;&amp;gt;
				&amp;lt;!-- Optional social links --&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex&amp;quot;&amp;gt;

			&amp;lt;div&amp;gt;
				&amp;lt;div class=&amp;quot;text-muted&amp;quot;&amp;gt;@&amp;lt;span data-v-admin-username&amp;gt;username&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;

				&amp;lt;div&amp;gt;
					&amp;lt;a class=&amp;quot;d-block&amp;quot; data-v-admin-website href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-admin-website&amp;gt;example.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-admin-public_email&amp;gt;admin@vvveb.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-admin-phone_number&amp;gt;123456&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;
				&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;ms-5&amp;quot;&amp;gt;
				&amp;lt;div data-v-admin-bio&amp;gt;My bio&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

		&amp;lt;/div&amp;gt;

	&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;
</code></pre>
<p>This example displays a list of up to four admin users, each rendered using the available admin properties.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="211">
			<title data-v-post-name="name">Posts Component</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/posts</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Posts component displays a list of posts anywhere in your theme. It supports pagination, filtering, sorting, taxonomy filtering, author filtering, and optional image galleries. This makes it suita]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Posts</strong> component displays a list of posts anywhere in your theme.
It supports pagination, filtering, sorting, taxonomy filtering, author filtering, and optional image galleries. This makes it suitable for blog pages, category pages, search results, or custom post listings.</p>
<h2>Component Properties</h2>
<p>Inside the component, the following repeatable post properties are available. Each post is wrapped in an element marked with <code>data-v-post</code>.</p>
<ul>
<li><strong>name</strong> — <code>data-v-post-name</code> — Post title.</li>
<li><strong>content</strong> — <code>data-v-post-content</code> — Post content.</li>
<li><strong>excerpt</strong> — <code>data-v-post-excerpt</code> — Post excerpt.</li>
<li><strong>status</strong> — <code>data-v-post-status</code> — Post status (<code>publish</code>, <code>disabled</code>, <code>scheduled</code>).</li>
<li><strong>image</strong> — <code>data-v-post-image</code> — Main post image.</li>
<li><strong>slug</strong> — <code>data-v-post-url</code> — Post slug.</li>
<li><strong>url</strong> — <code>data-v-post-url</code> — Post detail page URL.</li>
<li><strong>meta_keywords</strong> — <code>data-v-post-meta_keywords</code> — Post meta keywords.</li>
<li><strong>meta_description</strong> — <code>data-v-post-meta_description</code> — Post meta description.</li>
<li><strong>type</strong> — <code>data-v-post-type</code> — Post type, default is <code>post</code>.</li>
<li><strong>password</strong> — <code>data-v-post-password</code> — Post password if is password protected.</li>
<li><strong>comment_status</strong> — <code>data-v-post-comment_status</code> — Post comment status, if comments are allowed or disabled</li>
<li><strong>comment_count</strong> — <code>data-v-post-comment_count</code> — Number of comments on the post</li>
<li><strong>views</strong> — <code>data-v-post-comment_count</code> — Number of views on the post</li>
<li><strong>sort_order</strong> — <code>data-v-post-sort_order</code> — Post sort order.</li>
<li><strong>template</strong> — <code>data-v-post-template</code> — Template used to render the post if a different template is used.</li>
</ul>
<p>These properties repeat for each post returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;div data-v-component-posts 
     data-v-limit=&amp;quot;10&amp;quot; 
     data-v-page=&amp;quot;2&amp;quot;&amp;gt;

    &amp;lt;div data-v-post&amp;gt;
        &amp;lt;a href=&amp;quot;#&amp;quot; data-v-post-url&amp;gt;
			&amp;lt;span data-v-post-name&amp;gt;Post name placeholder&amp;lt;/span&amp;gt;
		&amp;lt;/a&amp;gt;
        
        &amp;lt;span data-v-post-excerpt&amp;gt;Lorem ipsum&amp;lt;/span&amp;gt;
        &amp;lt;span data-v-post-content&amp;gt;Lorem ipsum&amp;lt;/span&amp;gt;
        
        &amp;lt;img src=&amp;quot;&amp;quot; data-v-post-image&amp;gt;
        
        &amp;lt;a href=&amp;quot;#&amp;quot; data-v-post-url&amp;gt;View post&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;
</code></pre>
<p>This example loads 10 posts from page 2, without including the image gallery. Each post is rendered inside the <code>data-v-post</code> block.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="212">
			<title data-v-post-name="name">Breadcrumb Component</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/breadcrumb</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The breadcrumb component generates a navigational trail that shows users where they are within your site structure. It can be placed anywhere in your theme and automatically adapts to pages, posts, pr]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>breadcrumb</strong> component generates a navigational trail that shows users where they are within your site structure. It can be placed anywhere in your theme and automatically adapts to pages, posts, products, categories, and other content types.</p>
<h2>Component Properties</h2>
<p>Each breadcrumb item is rendered inside an element marked with <code>data-v-breadcrumb-item</code>. The following properties are available for each item:</p>
<ul>
<li><strong>text</strong> — <code>data-v-breadcrumb-item-text</code> — The visible label of the breadcrumb item.</li>
<li><strong>url</strong> — <code>data-v-breadcrumb-item-url</code> — The link for the breadcrumb item. If empty, the item is displayed as plain text (typically the current page).</li>
</ul>
<p>The component repeats these properties for every breadcrumb segment, from the homepage to the current page.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;nav aria-label=&amp;quot;breadcrumb&amp;quot; class=&amp;quot;text-muted text-small&amp;quot; data-v-component-breadcrumb&amp;gt;
  &amp;lt;ol class=&amp;quot;breadcrumb&amp;quot;&amp;gt;

    &amp;lt;li class=&amp;quot;breadcrumb-item&amp;quot; data-v-breadcrumb-item&amp;gt;
      &amp;lt;a data-v-breadcrumb-item-url data-v-if=&amp;quot;breadcrumb.url&amp;quot;&amp;gt;
        &amp;lt;span data-v-breadcrumb-item-text&amp;gt;Home&amp;lt;/span&amp;gt;
      &amp;lt;/a&amp;gt;
      &amp;lt;span data-v-breadcrumb-item-text data-v-if-not=&amp;quot;breadcrumb.url&amp;quot;&amp;gt;Home&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;

    &amp;lt;li class=&amp;quot;breadcrumb-item&amp;quot; data-v-breadcrumb-item&amp;gt;
      &amp;lt;a data-v-breadcrumb-item-url data-v-if=&amp;quot;breadcrumb.url&amp;quot;&amp;gt;
        &amp;lt;span data-v-breadcrumb-item-text&amp;gt;Library&amp;lt;/span&amp;gt;
      &amp;lt;/a&amp;gt;
      &amp;lt;span data-v-breadcrumb-item-text data-v-if-not=&amp;quot;breadcrumb.url&amp;quot;&amp;gt;Library&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;

    &amp;lt;li class=&amp;quot;breadcrumb-item active&amp;quot; aria-current=&amp;quot;page&amp;quot; data-v-breadcrumb-item&amp;gt;
      &amp;lt;span data-v-breadcrumb-item-text&amp;gt;Data&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;

  &amp;lt;/ol&amp;gt;
&amp;lt;/nav&amp;gt;
</code></pre>
<p>This example shows a typical breadcrumb structure with conditional links: if a breadcrumb item has a URL, it is rendered as a link; otherwise, it appears as plain text (usually the current page).</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="213">
			<title data-v-post-name="name">Users Component</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/users</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Improve the following documentation for Users component in Vvveb CMS 
The users component displays a list of useristrator users. It supports pagination, filtering, and searching, making it useful for ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<p>Improve the following documentation for Users component in Vvveb CMS</p>

<p>The <strong>users</strong> component displays a list of useristrator users.
It supports pagination, filtering, and searching, making it useful for author listings, team pages, or user management sections within a theme.</p>
<h2>Component Properties</h2>
<p>Each user user is wrapped in an element marked with <code>data-v-user</code>.<br />
Inside each element, the following properties are available:</p>
<ul>
<li><strong>first_name</strong> — <code>data-v-user-first_name</code> — User’s first name.</li>
<li><strong>last_name</strong> — <code>data-v-user-last_name</code> — User’s last name.</li>
<li><strong>avatar_url</strong> — <code>data-v-user-avatar_url</code> — Profile avatar image URL.</li>
<li><strong>cover_url</strong> — <code>data-v-user-cover_url</code> — Cover or background image URL.</li>
<li><strong>url</strong> — <code>data-v-user-url</code> — Public profile page URL.</li>
<li><strong>username</strong> — <code>data-v-user-username</code> — Username used for login.</li>
<li><strong>display_name</strong> — <code>data-v-user-display_name</code> — Public display name.</li>
<li><strong>website</strong> — <code>data-v-user-website</code> — Personal or professional website.</li>
<li><strong>email</strong> — <code>data-v-user-email</code> — Internal email for login and notifications.</li>
<li><strong>public_email</strong> — <code>data-v-user-public_email</code> — Publicly visible email address.</li>
<li><strong>bio</strong> — <code>data-v-user-bio</code> — Short biography or description.</li>
<li><strong>created_at</strong> — <code>data-v-user-created_at</code> — Account creation timestamp.</li>
<li><strong>updated_at</strong> — <code>data-v-user-updated_at</code> — Last update timestamp.</li>
<li><strong>last_ip</strong> — <code>data-v-user-last_ip</code> — Last login IP address.</li>
<li><strong>phone_number</strong> — <code>data-v-user-phone_number</code> — Public phone number (if provided).</li>
</ul>
<p>These properties repeat for each user returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;div data-v-component-users data-v-limit=&amp;quot;4&amp;quot;&amp;gt;

	&amp;lt;div data-v-user&amp;gt;

		&amp;lt;div class=&amp;quot;profile-header&amp;quot;&amp;gt;
			&amp;lt;div class=&amp;quot;cover&amp;quot;&amp;gt;
				&amp;lt;img src=&amp;quot;&amp;quot; data-v-user-cover_url&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;avatar&amp;quot;&amp;gt;
				&amp;lt;img data-v-user-avatar_url class=&amp;quot;rounded-circle avatar&amp;quot; alt=&amp;quot;Profile Picture&amp;quot;&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex justify-content-between&amp;quot;&amp;gt;
			&amp;lt;div&amp;gt;
				&amp;lt;h1 class=&amp;quot;h3 m-0&amp;quot; data-v-user-display_name&amp;gt;User&amp;lt;/h1&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;social-links d-inline-block&amp;quot;&amp;gt;
				&amp;lt;!-- Optional social links --&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex&amp;quot;&amp;gt;

			&amp;lt;div&amp;gt;
				&amp;lt;div class=&amp;quot;text-muted&amp;quot;&amp;gt;@&amp;lt;span data-v-user-username&amp;gt;username&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;

				&amp;lt;div&amp;gt;
					&amp;lt;a class=&amp;quot;d-block&amp;quot; data-v-user-website href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-user-website&amp;gt;example.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-user-public_email&amp;gt;user@vvveb.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-user-phone_number&amp;gt;123456&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;
				&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;ms-5&amp;quot;&amp;gt;
				&amp;lt;div data-v-user-bio&amp;gt;My bio&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

		&amp;lt;/div&amp;gt;

	&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;
</code></pre>
<p>This example displays a list of up to four user users, each rendered using the available user properties.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="214">
			<title data-v-post-name="name">Products Component</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/products</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Products component displays a list of products on any page or template. It supports filtering, sorting, pagination, and optional image galleries, making it suitable for category pages, featured pr]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Products</strong> component displays a list of products on any page or template. It supports filtering, sorting, pagination, and optional image galleries, making it suitable for category pages, featured product sections, search results, or custom product listings.</p>
<h2>Component Properties</h2>
<p>Inside the component, the following repeatable product properties are available. Each product is wrapped in an element marked with <code>data-v-product</code>.</p>
<ul>
<li><strong>name</strong> — <code>data-v-product-name</code> — Product name.</li>
<li><strong>content</strong> — <code>data-v-product-content</code> — Product description or content.</li>
<li><strong>price</strong> — <code>data-v-product-price</code> — Product price.</li>
<li><strong>image</strong> — <code>data-v-product-image</code> — Main product image.</li>
<li><strong>images</strong> — <code>data-v-product-images</code> — Product gallery images.</li>
<li><strong>url</strong> — <code>data-v-product-url</code> — Product detail page URL.</li>
</ul>
<p>These properties repeat for each product returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;div data-v-component-products 
     data-v-limit=&amp;quot;10&amp;quot; 
     data-v-page=&amp;quot;2&amp;quot; 
     data-v-order=&amp;quot;price&amp;quot;
     data-v-direction=&amp;quot;asc&amp;quot;
     data-v-include_image_gallery=&amp;quot;false&amp;quot;&amp;gt;

    &amp;lt;div class=&amp;quot;product-card&amp;quot; data-v-product&amp;gt;
        &amp;lt;img src=&amp;quot;/placeholder.jpg&amp;quot; data-v-product-image alt=&amp;quot;Product Image&amp;quot;&amp;gt;
        
        &amp;lt;h3 data-v-product-name&amp;gt;Product Name Placeholder&amp;lt;/h3&amp;gt;
        &amp;lt;p data-v-product-content&amp;gt;Short description goes here...&amp;lt;/p&amp;gt;
        
        &amp;lt;span class=&amp;quot;price&amp;quot; data-v-product-price&amp;gt;$0.00&amp;lt;/span&amp;gt;
        
        &amp;lt;a href=&amp;quot;#&amp;quot; data-v-product-url class=&amp;quot;button&amp;quot;&amp;gt;View Product&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
    
    &amp;lt;div data-v-if-not=&amp;quot;products&amp;quot;&amp;gt;
        &amp;lt;p&amp;gt;No products match your criteria.&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
</code></pre>
<p>This example loads 10 products from page 2, without including the image gallery. Each product is rendered inside the <code>data-v-product</code> block.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="215">
			<title data-v-post-name="name">Admin Component</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/admin</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The admin component displays information about an administrator user. If no admin_id or username is provided, the component automatically shows the currently logged‑in admin user. This makes it usef]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>admin</strong> component displays information about an administrator user.
If no <code>admin_id</code> or <code>username</code> is provided, the component automatically shows the currently logged‑in admin user.
This makes it useful for author profile pages, dashboards, or any template where admin details are needed.</p>
<h2>Component Properties</h2>
<p>The following properties are available inside the component. Each property can be used with its corresponding <code>data-v-admin-*</code> attribute.</p>
<ul>
<li><strong>first_name</strong> — <code>data-v-admin-first_name</code> — Admin’s first name.</li>
<li><strong>last_name</strong> — <code>data-v-admin-last_name</code> — Admin’s last name.</li>
<li><strong>avatar_url</strong> — <code>data-v-admin-avatar_url</code> — URL of the admin’s profile avatar.</li>
<li><strong>cover_url</strong> — <code>data-v-admin-cover_url</code> — URL of the admin’s cover/background image.</li>
<li><strong>url</strong> — <code>data-v-admin-url</code> — Link to the admin’s public profile page.</li>
<li><strong>username</strong> — <code>data-v-admin-username</code> — Admin’s username.</li>
<li><strong>display_name</strong> — <code>data-v-admin-display_name</code> — Public display name.</li>
<li><strong>website</strong> — <code>data-v-admin-website</code> — Personal or professional website.</li>
<li><strong>email</strong> — <code>data-v-admin-email</code> — Internal email used for login and notifications.</li>
<li><strong>public_email</strong> — <code>data-v-admin-public_email</code> — Publicly visible email address.</li>
<li><strong>bio</strong> — <code>data-v-admin-bio</code> — Short biography or description.</li>
<li><strong>created_at</strong> — <code>data-v-admin-created_at</code> — Account creation timestamp.</li>
<li><strong>updated_at</strong> — <code>data-v-admin-updated_at</code> — Last update timestamp.</li>
<li><strong>role_id</strong> — <code>data-v-admin-role_id</code> — Role ID assigned to the admin.</li>
<li><strong>role</strong> — <code>data-v-admin-role</code> — Role name (e.g., Administrator, Editor).</li>
<li><strong>last_ip</strong> — <code>data-v-admin-last_ip</code> — Last login IP address.</li>
<li><strong>phone_number</strong> — <code>data-v-admin-phone_number</code> — Public phone number (if provided).</li>
</ul>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;div data-v-component-admin data-v-admin_id=&amp;quot;url&amp;quot; class=&amp;quot;profile&amp;quot;&amp;gt;

	&amp;lt;div data-v-if=&amp;quot;admin&amp;quot;&amp;gt;

		&amp;lt;div class=&amp;quot;profile-header&amp;quot;&amp;gt;
			&amp;lt;div class=&amp;quot;cover&amp;quot;&amp;gt;
				&amp;lt;img src=&amp;quot;&amp;quot; data-v-admin-cover_url&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;avatar&amp;quot;&amp;gt;
				&amp;lt;img data-v-admin-avatar_url class=&amp;quot;rounded-circle avatar&amp;quot; alt=&amp;quot;Profile Picture&amp;quot;&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex justify-content-between&amp;quot;&amp;gt;
			&amp;lt;div&amp;gt;
				&amp;lt;h1 class=&amp;quot;h3 m-0&amp;quot; data-v-admin-display_name&amp;gt;User&amp;lt;/h1&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;social-links d-inline-block&amp;quot;&amp;gt;
				&amp;lt;!-- Optional social links --&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex&amp;quot;&amp;gt;

			&amp;lt;div&amp;gt;
				&amp;lt;div class=&amp;quot;text-muted&amp;quot;&amp;gt;@&amp;lt;span data-v-admin-username&amp;gt;username&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;

				&amp;lt;div&amp;gt;
					&amp;lt;a class=&amp;quot;d-block&amp;quot; data-v-admin-website href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-admin-website&amp;gt;example.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-admin-public_email&amp;gt;admin@vvveb.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-admin-phone_number&amp;gt;123456&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;
				&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;ms-5&amp;quot;&amp;gt;
				&amp;lt;div data-v-admin-bio&amp;gt;My bio&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

		&amp;lt;/div&amp;gt;

	&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;
</code></pre>
<p>This example loads the admin profile based on the <code>admin_id</code> found in the URL. All admin details are displayed using the component’s data attributes.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="216">
			<title data-v-post-name="name">Component user</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/user</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 28 Feb 2026 23:04:20 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The user component displays information about an useristrator user. If no user_id or username is provided, the component automatically shows the currently logged‑in user user. This makes it useful f]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>user</strong> component displays information about an useristrator user.
If no <code>user_id</code> or <code>username</code> is provided, the component automatically shows the currently logged‑in user user.
This makes it useful for author profile pages, dashboards, or any template where user details are needed.</p>
<h2>Component Properties</h2>
<p>The following properties are available inside the component. Each property can be used with its corresponding <code>data-v-user-*</code> attribute.</p>
<ul>
<li><strong>first_name</strong> — <code>data-v-user-first_name</code> — Admin’s first name.</li>
<li><strong>last_name</strong> — <code>data-v-user-last_name</code> — Admin’s last name.</li>
<li><strong>avatar_url</strong> — <code>data-v-user-avatar_url</code> — URL of the user’s profile avatar.</li>
<li><strong>cover_url</strong> — <code>data-v-user-cover_url</code> — URL of the user’s cover/background image.</li>
<li><strong>url</strong> — <code>data-v-user-url</code> — Link to the user’s public profile page.</li>
<li><strong>username</strong> — <code>data-v-user-username</code> — Admin’s username.</li>
<li><strong>display_name</strong> — <code>data-v-user-display_name</code> — Public display name.</li>
<li><strong>website</strong> — <code>data-v-user-website</code> — Personal or professional website.</li>
<li><strong>email</strong> — <code>data-v-user-email</code> — Internal email used for login and notifications.</li>
<li><strong>public_email</strong> — <code>data-v-user-public_email</code> — Publicly visible email address.</li>
<li><strong>bio</strong> — <code>data-v-user-bio</code> — Short biography or description.</li>
<li><strong>created_at</strong> — <code>data-v-user-created_at</code> — Account creation timestamp.</li>
<li><strong>updated_at</strong> — <code>data-v-user-updated_at</code> — Last update timestamp.</li>
<li><strong>role_id</strong> — <code>data-v-user-role_id</code> — Role ID assigned to the user.</li>
<li><strong>role</strong> — <code>data-v-user-role</code> — Role name (e.g., Administrator, Editor).</li>
<li><strong>last_ip</strong> — <code>data-v-user-last_ip</code> — Last login IP address.</li>
<li><strong>phone_number</strong> — <code>data-v-user-phone_number</code> — Public phone number (if provided).</li>
</ul>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&amp;lt;div data-v-component-user data-v-user_id=&amp;quot;url&amp;quot; class=&amp;quot;profile&amp;quot;&amp;gt;

	&amp;lt;div data-v-if=&amp;quot;user&amp;quot;&amp;gt;

		&amp;lt;div class=&amp;quot;profile-header&amp;quot;&amp;gt;
			&amp;lt;div class=&amp;quot;cover&amp;quot;&amp;gt;
				&amp;lt;img src=&amp;quot;&amp;quot; data-v-user-cover_url&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;avatar&amp;quot;&amp;gt;
				&amp;lt;img data-v-user-avatar_url class=&amp;quot;rounded-circle avatar&amp;quot; alt=&amp;quot;Profile Picture&amp;quot;&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex justify-content-between&amp;quot;&amp;gt;
			&amp;lt;div&amp;gt;
				&amp;lt;h1 class=&amp;quot;h3 m-0&amp;quot; data-v-user-display_name&amp;gt;User&amp;lt;/h1&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;social-links d-inline-block&amp;quot;&amp;gt;
				&amp;lt;!-- Optional social links --&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;

		&amp;lt;div class=&amp;quot;px-3 m-3 me-5 d-flex&amp;quot;&amp;gt;

			&amp;lt;div&amp;gt;
				&amp;lt;div class=&amp;quot;text-muted&amp;quot;&amp;gt;@&amp;lt;span data-v-user-username&amp;gt;username&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;

				&amp;lt;div&amp;gt;
					&amp;lt;a class=&amp;quot;d-block&amp;quot; data-v-user-website href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-user-website&amp;gt;example.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-user-public_email&amp;gt;user@vvveb.com&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;

					&amp;lt;a class=&amp;quot;d-block text-body small&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
						&amp;lt;span data-v-user-phone_number&amp;gt;123456&amp;lt;/span&amp;gt;
					&amp;lt;/a&amp;gt;
				&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

			&amp;lt;div class=&amp;quot;ms-5&amp;quot;&amp;gt;
				&amp;lt;div data-v-user-bio&amp;gt;My bio&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;

		&amp;lt;/div&amp;gt;

	&amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;
</code></pre>
<p>This example loads the user profile based on the <code>user_id</code> found in the URL. All user details are displayed using the component’s data attributes.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="169">
			<title data-v-post-name="name">Plugin structure</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/plugin-structure</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 18 Jul 2025 00:40:29 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="170">
			<title data-v-post-name="name">VTpl A CSS‑Selector‑Driven PHP Template Engine</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/vvveb-vtpl</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Fri, 18 Jul 2025 00:40:29 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Vtpl is a PHP template engine designed to keep HTML clean, readable, and free of embedded logic. Instead of mixing PHP code directly into HTML, Vtpl uses CSS selectors to define where dynamic content ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Vtpl is a PHP template engine designed to keep HTML clean, readable, and free of embedded logic.
Instead of mixing PHP code directly into HTML, Vtpl uses <strong>CSS selectors</strong> to define where dynamic content should be inserted.
This separation of concerns makes templates easier to maintain, theme, and redesign, especially in CMS environments where HTML changes frequently.</p>
<p>With Vtpl, templates are simply lists of rules that map:</p>
<pre><code>CSS selector  →  PHP variable or PHP code
</code></pre>
<p>Because the HTML remains untouched, designers can modify layouts freely while developers maintain logic independently. This approach enables systems like <strong>Vvveb CMS</strong>, where any HTML file can be replaced or redesigned without breaking dynamic content rendering.</p>
<h1>Including HTML from Other Templates</h1>
<p>Vtpl supports reusing HTML fragments using the <code>from</code> directive. This is useful for shared elements like headers, footers, or repeated UI blocks.</p>
<pre><code class="language-css">div#top &gt; div.header = from(homepage.html|div#top &gt; div.header)
</code></pre>
<p>If no selector is provided, Vtpl assumes the same selector (eg div#top &gt; div.header):</p>
<pre><code class="language-css">div#top &gt; div.header = from(homepage.html)
</code></pre>
<p>This ensures consistent markup across templates without duplicating HTML.</p>
<hr />
<h1>Modifiers</h1>
<p>Modifiers change how Vtpl inserts content into the selected elements.</p>
<h3>innerHTML (default)</h3>
<p>Replaces the inside of the element.</p>
<pre><code class="language-css">div#id &gt; span.title = &quot;Lorem ipsum&quot;
div#id &gt; span.title|innerHTML = &quot;Lorem ipsum&quot;
</code></pre>
<h3>outerHTML</h3>
<p>To replace the entire elements with the specified code use outerHTML modifier</p>
<pre><code class="language-css">div#id &gt; span.title|outerHTML = &quot;Lorem ipsum&quot;
</code></pre>
<h3>innerText</h3>
<p>To replace only the first text inside element but leave other elements intact</p>
<pre><code class="language-css">div#id &gt; span.title|innerText = &quot;Lorem ipsum&quot;
</code></pre>
<h3>before</h3>
<p>Inserts content before the element.</p>
<pre><code class="language-css">div#id &gt; span.class a|before = &quot;lorem ipsum&quot;
</code></pre>
<h3>prepend</h3>
<p>Inserts content at the beginning of the element.</p>
<pre><code class="language-css">div#id &gt; span.class a|prepend = &quot;lorem ipsum&quot;
</code></pre>
<h3>after</h3>
<p>Inserts content after the element.</p>
<pre><code class="language-css">div#id &gt; span.class a|after = &quot;lorem ipsum&quot;
</code></pre>
<h3>append</h3>
<p>Inserts content at the end of the element.</p>
<pre><code class="language-css">div#id &gt; span.class a|append = &quot;lorem ipsum&quot;
</code></pre>
<h3>deleteAllButFirst</h3>
<p>Keeps only the first matched element, useful when designers include multiple mock elements but we only need one to iterate.</p>
<pre><code class="language-css">div.items a|deleteAllButFirst
</code></pre>
<p>Example:</p>
<pre><code class="language-html">&lt;!-- Original --&gt;
&lt;div class=&quot;items&quot;&gt;
  &lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
  &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
  &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
&lt;/div&gt;

&lt;!-- After deleteAllButFirst --&gt;
&lt;div class=&quot;items&quot;&gt;
  &lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
&lt;/div&lt;
</code></pre>
<h3>hide (conditional rendering)</h3>
<p>Removes elements if a variable is empty or false.</p>
<pre><code class="language-css">div.articles|if_exists = $articles
</code></pre>
<h3>delete</h3>
<p>Removes the selected elements entirely.</p>
<pre><code class="language-css">div.ad-banner|delete
</code></pre>
<h3>Attribute insert</h3>
<p>To modify an attribute, specify it as a modifier:</p>
<pre><code class="language-css">a.button|href = $url
a.button|title = &quot;Go to page&quot;
</code></pre>
<hr />
<h1>Additional Commands</h1>
<h3>import</h3>
<p>Includes another Vtpl file. Useful for splitting large templates into smaller, maintainable parts.</p>
<pre><code class="language-css">import(profile/activity_tab.tpl)
</code></pre>
<hr />
<h1>Comments</h1>
<p>Vtpl supports both single‑line and multi‑line comments:</p>
<pre><code class="language-css">// Single line comment

/* 
Multi-line
comment
*/
</code></pre>
<hr />
<h1>Debugging</h1>
<p>Enable debugging inside a Vtpl file:</p>
<pre><code class="language-css">debug = true
</code></pre>
<p>Disable it:</p>
<pre><code class="language-css">debug = false
</code></pre>
<p>When debugging is enabled, Vtpl outputs a list of all template inserts, helping you understand exactly how the HTML was transformed.</p>
<hr />
<p>Vtpl’s CSS‑selector‑based approach keeps HTML clean, separates logic from presentation, and makes large CMS systems easier to theme and maintain.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="163">
			<title data-v-post-name="name">GraphQL</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/graphql</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 14 Dec 2024 20:06:38 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Vvveb GraphQL API allows you to build headless storefronts, mobile apps, and custom integrations by querying only the data you need. 
It follows a schema-first approach, providing a flexible alter]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The Vvveb GraphQL API allows you to build headless storefronts, mobile apps, and custom integrations by querying only the data you need.</p>
<p>It follows a schema-first approach, providing a flexible alternative to traditional REST endpoints.</p>
<hr />
<h2>1. Setup &amp; Requirements</h2>
<p>By default, the GraphQL API is disabled for security. To get started, you must enable the feature and install the core library.</p>
<h3>Enable the API</h3>
<p>Edit your <code>env.php</code> file (located in the root directory) and set the <code>GRAPHQL</code> constant to <code>true</code>:</p>
<pre><code class="language-php">defined('GRAPHQL') || define('GRAPHQL', true);

</code></pre>
<blockquote>
<p><strong>Tip:</strong> If you don't have SSH/FTP access, you can edit this file via the <a href="https://plugins.vvveb.com/plugin/file-manager">File Manager Plugin</a>.</p>
</blockquote>
<h3>Install Dependencies</h3>
<p>Vvveb relies on the <code>webonyx/graphql-php</code> library. Choose one of the following methods:</p>
<h4>Via Composer:</h4>
<p>Run the following command from your Vvveb root:</p>
<pre><code class="language-bash">composer require webonyx/graphql-php

</code></pre>
<h4>Via Plugin</h4>
<p>If you don't have access to command line to run composer , install the <a href="https://plugins.vvveb.com/product/graphql-lib">GraphQL Lib Plugin</a>.</p>
<hr />
<h2>2. Authentication &amp; Permissions</h2>
<p>Access to the GraphQL endpoint is restricted to authorized users. You must use an account that has been assigned a <strong>GraphQL Role</strong> in the admin panel.</p>
<h3>Authentication Methods</h3>
<p>You can authenticate your requests using either <strong>HTTP Basic Auth</strong> (for development) or <strong>Bearer Tokens</strong> (for production).</p>
<h4>Option A: Bearer Token (Recommended)</h4>
<pre><code class="language-bash">curl -i -H 'Content-Type: application/json' \
     -H &quot;Authorization: Bearer YOUR_TOKEN&quot; \
     -X POST \
     -d '{&quot;query&quot;:&quot;{ posts { nodes { postId name content } } }&quot;}' \
     'https://demo.vvveb.com/graphql'

</code></pre>
<h4>Option B: Basic Auth</h4>
<pre><code class="language-bash">curl --user demo:demo -i \
     -H 'Content-Type: application/json' \
     -X POST \
     --data-raw '{&quot;query&quot;:&quot;{ posts { nodes { postId name content } } }&quot;}' \
     'https://demo.vvveb.com/graphql'

</code></pre>
<h3>Granular Permissions</h3>
<p>Permissions are managed under <strong>User Roles</strong> in the Vvveb Admin. You can restrict access based on:</p>
<ul>
<li><strong>Resource:</strong> (e.g., allow reading <code>posts</code> but not <code>orders</code>).</li>
<li><strong>Action:</strong> (e.g., allow <code>query</code> but block <code>mutation</code>).</li>
</ul>
<hr />
<h2>3. Development Tools</h2>
<h3>GraphQL IDE</h3>
<p>To explore the schema and test queries visually, install the <a href="https://plugins.vvveb.com/product/graphql">GraphQL IDE Plugin</a>. This provides an interactive GraphiQL interface directly in your browser.</p>
<h3>Headless Integration (Next.js)</h3>
<p>Vvveb CMS is fully compatible with <strong>Vercel Next.js Commerce</strong>. This allows you to deploy a high-performance React frontend while using Vvveb as your robust backend.</p>
<ul>
<li><strong>Source Code:</strong> <a href="https://github.com/givanz/vercel-vvveb-commerce">Vvveb Next.js Commerce on GitHub</a></li>
<li><strong>Live Demo:</strong> <a href="https://vercel-vvveb-commerce.vercel.app">vercel-vvveb-commerce.vercel.app</a></li>
</ul>
<hr />
<p>To fetch products effectively via the Vvveb GraphQL API, you should use a query that includes pagination arguments (like <code>page</code> and <code>limit</code>) and requests the <code>pageInfo</code> object to determine if more data is available.</p>
<hr />
<h3>Paginated Products Query</h3>
<p>This query retrieves the first <strong>3 products</strong>, including their IDs, names, slugs, and formatted prices.</p>
<pre><code class="language-graphql">
query getProducts {
    products(limit:3) {
       pageInfo {
         count
         page
         limit
       }
        nodes {
          ...product
        }
    }
  }
  
  fragment product on ProductType {
      productId
      slug
      stockQuantity
      name
      content
      createdAt
      updatedAt

      price
     priceCurrency
      variants {
        productId
        productVariantId
        image
        price
        stockQuantity
        weight
        sku
        barcode
      }
      image
      image
      options {
        productOptionId
        productId
        optionId
        name
        value
        required
        values {
        	name
        }
      }
      variants {
        productId
        productVariantId
        image
        price
        stockQuantity
        weight
        sku
        barcode
      }
      images {
        productImageId
        productId
        image
        sortOrder
      }
      seo {
        og {
          title
          description
        }
        twitter {
          title
          content
          label1
          data1
          label2
          data2
        }
      }
      sites {
        siteId
        name
      }
  }

</code></pre>
<h3>Parameter Breakdown</h3>
<table class="table">
<thead>
<tr>
<th>Argument</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>limit</code></td>
<td>The number of items to return (e.g., <code>10</code>).</td>
</tr>
<tr>
<td><code>page</code></td>
<td>The page number to return.</td>
</tr>
<tr>
<td><code>count</code></td>
<td>The number of products available, useful for calculating the total number of pages in your UI.</td>
</tr>
</tbody>
</table>
<hr />
<h3>Example JSON Response</h3>
<p>When you execute the query, the API returns a structured JSON object. Notice how the <code>price</code> is often returned as an object containing both the raw numeric value and the currency-formatted string.</p>
<pre><code class="language-json">{
  &quot;data&quot;: {
    &quot;products&quot;: {
      &quot;pageInfo&quot;: {
        &quot;count&quot;: 0,
        &quot;page&quot;: 1,
        &quot;limit&quot;: 10
      },
      &quot;nodes&quot;: [
        {
          &quot;productId&quot;: &quot;19&quot;,
          &quot;slug&quot;: &quot;product-nineteen&quot;,
          &quot;stockQuantity&quot;: 1000,
          &quot;name&quot;: &quot;Product 19&quot;,
          &quot;price&quot;: {
            &quot;regularPrice&quot;: 89.99,
            &quot;formattedPrice&quot;: &quot;$89.99&quot;
          },
          &quot;image&quot;: {
            &quot;url&quot;: &quot;https://yoursite.com/media/products/kb.jpg&quot;,
            &quot;altText&quot;: &quot;RGB Mechanical Keyboard&quot;
          }
        }
      ]
    }
  }
}

</code></pre>
<hr />
<h3>Pro Tip: Filtering by Category</h3>
<p>If you want to fetch products from a specific category, you can usually add a <code>filter</code> or <code>taxonomyId</code> argument to the <code>products</code> query:
<code>products(first: 10, filter: { taxonomyId: 5 }) { ... }</code></p>
<p>Adding a product to a cart is a <strong>Mutation</strong> because it modifies the state of the server-side data. In Vvveb CMS, this typically requires a <code>productId</code> and a <code>quantity</code>. If your product has variants (like size or color), you would also pass an <code>option</code> array or a <code>variantId</code>.</p>
<hr />
<h3>Add to Cart Mutation</h3>
<p>This mutation adds a specific quantity of a product to the current session's cart and returns the updated cart totals and item list.</p>
<pre><code class="language-graphql">mutation AddToCart($productId: ID!, $quantity: Int!) {
  addToCart(input: { productId: $productId, quantity: $quantity }) {
    cart {
      total {
        amount
        formatted
      }
      items {
        cartItemId
        name
        quantity
        price {
          formattedPrice
        }
        total {
          formattedPrice
        }
      }
    }
    errors {
      message
      code
    }
  }
}

</code></pre>
<hr />
<h3>Example Variables</h3>
<p>Pass these alongside your query to specify which product you're snagging.</p>
<pre><code class="language-json">{
  &quot;productId&quot;: &quot;101&quot;,
  &quot;quantity&quot;: 2
}

</code></pre>
<hr />
<h3>Example JSON Response</h3>
<p>If successful, the API returns the current state of the cart so you can update your UI (like a mini-cart or toast notification) immediately.</p>
<pre><code class="language-json">{
  &quot;data&quot;: {
    &quot;addToCart&quot;: {
      &quot;cart&quot;: {
        &quot;total&quot;: {
          &quot;amount&quot;: 179.98,
          &quot;formatted&quot;: &quot;$179.98&quot;
        },
        &quot;items&quot;: [
          {
            &quot;cartItemId&quot;: &quot;item_abc123&quot;,
            &quot;name&quot;: &quot;Mechanical Keyboard&quot;,
            &quot;quantity&quot;: 2,
            &quot;price&quot;: { &quot;formattedPrice&quot;: &quot;$89.99&quot; },
            &quot;total&quot;: { &quot;formattedPrice&quot;: &quot;$179.98&quot; }
          }
        ]
      },
      &quot;errors&quot;: []
    }
  }
}

</code></pre>
<hr />
<h3>Key Integration Tips</h3>
<ul>
<li><strong>Session vs. Token:</strong> Vvveb usually handles the cart via the session cookie for web users. However, if you're building a mobile app, ensure your GraphQL client is configured to persist and send the <code>Authorization: Bearer</code> token or the session ID in the headers to keep the cart &quot;alive&quot; between requests.</li>
<li><strong>Error Handling:</strong> Always check the <code>errors</code> array in the response. A mutation might &quot;succeed&quot; at the network level but fail logically (e.g., if the product is out of stock).</li>
<li><strong>Optimistic UI:</strong> For a snappy feel, you can update your local UI state <em>before</em> the server responds, then roll it back if the <code>errors</code> array comes back populated.</li>
</ul>
<hr />
<p>Managing a cart effectively requires the ability to tweak quantities or change your mind about an item. In GraphQL, these are separate mutations that typically return the updated state of the entire cart so your UI stays in sync.</p>
<hr />
<h2>Update Item Quantity</h2>
<p>This mutation is used when a user clicks a &quot;plus&quot; or &quot;minus&quot; button or types a new number into a quantity field.</p>
<pre><code class="language-graphql">mutation UpdateCartItem($cartItemId: ID!, $quantity: Int!) {
  updateCartItem(input: { cartItemId: $cartItemId, quantity: $quantity }) {
    cart {
      total {
        formatted
      }
      items {
        cartItemId
        quantity
        total {
          formattedPrice
        }
      }
    }
    errors {
      message
    }
  }
}

</code></pre>
<h3>Example Variables</h3>
<pre><code class="language-json">{
  &quot;cartItemId&quot;: &quot;item_abc123&quot;,
  &quot;quantity&quot;: 5
}

</code></pre>
<hr />
<h2>Remove Item from Cart</h2>
<p>To completely delete an item, you only need the unique <code>cartItemId</code>.</p>
<pre><code class="language-graphql">mutation RemoveFromCart($cartItemId: ID!) {
  removeFromCart(input: { cartItemId: $cartItemId }) {
    cart {
      total {
        formatted
      }
      items {
        name
      }
    }
    errors {
      message
    }
  }
}

</code></pre>
<hr />
<h2>Implementation Best Practices</h2>
<ul>
<li><strong>The <code>cartItemId</code> vs <code>productId</code>:</strong> Always use the <code>cartItemId</code> for updates and removals. A <code>productId</code> isn't specific enough if a user has the same product in their cart with two different sets of options (e.g., one Blue shirt and one Red shirt).</li>
<li><strong>Zero Quantity Logic:</strong> In many GraphQL implementations, setting the <code>quantity</code> to <code>0</code> in the <code>updateCartItem</code> mutation will automatically trigger the removal of that item. Check your specific Vvveb schema to see if this shortcut is supported.</li>
<li><strong>Loading States:</strong> Since these requests happen over the network, disable the &quot;Quantity&quot; input or &quot;Remove&quot; button while the mutation is <code>loading</code> to prevent &quot;race conditions&quot; where a user clicks a button faster than the server can process.</li>
</ul>
<hr />
<p>To generate an accurate checkout summary, the API needs to calculate values based on the items in the cart and the user's destination. Usually, this query is executed after a shipping address has been set, as taxes and shipping rates are location-dependent.</p>
<hr />
<h2>Checkout Summary Query</h2>
<p>This query retrieves the full breakdown of the order, including available shipping carriers and a detailed tax summary.</p>
<pre><code class="language-graphql">query GetCheckoutSummary {
  checkout {
    cart {
      items {
        name
        quantity
        total {
          formattedPrice
        }
      }
      totals {
        subtotal {
          formatted
        }
        shipping {
          formatted
        }
        taxTotal {
          formatted
        }
        grandTotal {
          formatted
        }
      }
    }
    shippingMethods {
      code
      title
      cost {
        amount
        formatted
      }
      taxClassId
    }
    taxBreakdown {
      title
      rate
      amount {
        formatted
      }
    }
  }
}

</code></pre>
<hr />
<h2>Component Breakdown</h2>
<table class="table">
<thead>
<tr>
<th>Section</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong><code>cart.totals</code></strong></td>
<td>The financial &quot;Bottom Line.&quot; Includes the calculated subtotal, current shipping cost, and accumulated taxes.</td>
</tr>
<tr>
<td><strong><code>shippingMethods</code></strong></td>
<td>A list of available carriers (e.g., UPS, FedEx, Flat Rate). You would use the <code>code</code> from this list in a mutation to select a specific method.</td>
</tr>
<tr>
<td><strong><code>taxBreakdown</code></strong></td>
<td>Provides transparency by showing exactly which taxes are being applied (e.g., &quot;VAT 20%&quot; or &quot;State Tax 7%&quot;).</td>
</tr>
</tbody>
</table>
<hr />
<h2>Implementation Details</h2>
<ul>
<li><strong>Dynamic Updating:</strong> If your checkout is a &quot;Single Page&quot; app, you should re-run this query every time a user changes their shipping address or selects a different shipping method to ensure the <code>taxTotal</code> and <code>grandTotal</code> stay accurate.</li>
<li><strong>Address Dependency:</strong> In Vvveb CMS, if the <code>shippingMethods</code> array comes back empty, it usually means the user hasn't provided an address yet or no shipping rules match their location.</li>
<li><strong>Currency Logic:</strong> Always display the <code>formatted</code> values to the user to handle currency symbols and decimal placements correctly, while using the raw <code>amount</code> for any local JavaScript calculations if necessary.</li>
</ul>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="164">
			<title data-v-post-name="name">Rest Api</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/rest-api</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 14 Dec 2024 20:06:38 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Rest API Overview 
The Rest API allows external applications, such as mobile apps, static site generators, or headless frontends, to read and modify content stored in Vvveb CMS. 
It is disabled by def]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<h2>Rest API Overview</h2>
<p>The Rest API allows external applications, such as mobile apps, static site generators, or headless frontends, to read and modify content stored in Vvveb CMS.</p>
<p>It is disabled by default for security, and must be explicitly enabled before use.</p>
<p>Once active, the API exposes posts, products, users, taxonomies, and other resources through clean, predictable endpoints.</p>
<hr />
<h2>Enabling the Rest API</h2>
<p>The API is turned off by default. To enable it, edit <code>env.php</code> and set the <code>REST</code> constant to <code>true</code>:</p>
<pre><code class="language-php">defined('REST') || define('REST', true);
</code></pre>
<p>If you do not have direct access to server files, you can enable it using the  <a href="https://plugins.vvveb.com/plugin/file-manager">File manager plugin</a>, available in the plugin marketplace.</p>
<hr />
<h2>Authentication</h2>
<p>All API requests require authentication. Vvveb supports two methods:</p>
<ul>
<li><strong>Bearer tokens</strong></li>
<li><strong>HTTP Basic Authentication</strong> (username and password)</li>
</ul>
<p>Any admin user with the appropriate REST permissions can authenticate.</p>
<h3>Bearer token example</h3>
<pre><code class="language-bash">curl -H 'Authorization: Bearer mytoken' 'https://demo.vvveb.com/rest/posts/hello-world-1'
</code></pre>
<h3>Basic auth example</h3>
<pre><code class="language-bash">curl --user demo:demo 'https://demo.vvveb.com/rest/posts/hello-world-1'
</code></pre>
<p>Authentication is required for both reading and writing data unless a plugin or custom configuration explicitly exposes public endpoints.</p>
<hr />
<h2>Permissions and Access Control</h2>
<p>Access to API resources is controlled through <strong>admin roles</strong>. Permissions can be granted or restricted per:</p>
<ul>
<li><strong>Resource</strong> (posts, products, users, etc.)</li>
<li><strong>Action</strong> (read, write, update, delete)</li>
</ul>
<p>This ensures that only authorized users or applications can perform sensitive operations.</p>
<hr />
<h2>OpenAPI Documentation</h2>
<p>Interactive API documentation is available through the <a href="https://plugins.vvveb.com/product/openapi">Open Api plugin</a>, which automatically generates:</p>
<ul>
<li>Endpoint lists</li>
<li>Request/response schemas</li>
<li>Authentication examples</li>
<li>Live testing interface</li>
</ul>
<p>This is the recommended way to explore the full API surface.</p>
<hr />
<h2>Next.js Starter Project</h2>
<p>A ready‑to‑use example project is available for developers building headless frontends with Next.js. It demonstrates:</p>
<ul>
<li>Fetching posts via the REST API</li>
<li>Rendering content statically or dynamically</li>
<li>Using Vvveb as a headless CMS</li>
</ul>
<p>GitHub repository:<br />
<a href="https://github.com/givanz/nextjs-headless-rest-vvveb">https://github.com/givanz/nextjs-headless-rest-vvveb</a></p>
<p>Live demo:<br />
<a href="https://nextjs-headless-rest-vvveb.vercel.app/">https://nextjs-headless-rest-vvveb.vercel.app/</a></p>
<hr />
<p>The Rest API turns Vvveb into a flexible headless CMS, making it easy to integrate with modern frameworks and external applications.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="129">
			<title data-v-post-name="name">SqlP</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/sqlp</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[SqlP is a powerful ORM-like bridge between PHP and SQL in Vvveb CMS. It allows developers to write native SQL queries in .sql files while automatically generating PHP classes to interface with them. T]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p><strong>SqlP</strong> is a powerful ORM-like bridge between PHP and SQL in Vvveb CMS.
It allows developers to write native SQL queries in <code>.sql</code> files while automatically generating PHP classes to interface with them.
This approach maintains the performance of raw SQL without the &quot;spaghetti code&quot; of embedding long query strings inside PHP files.</p>
<hr />
<h2>File Structure</h2>
<p>SQL definitions are stored based on the database engine to ensure cross-compatibility:
<code>app/sql/{db-engine}/{filename}.sql</code></p>
<ul>
<li><strong>db-engine</strong>: <code>mysqli</code>, <code>pgsql</code>, or <code>sqlite</code>.</li>
<li><strong>Automatic Generation</strong>: For every <code>.sql</code> file, Vvveb generates a corresponding PHP class on the fly (e.g., <code>product.sql</code> becomes <code>ProductSQL</code> class).</li>
</ul>
<hr />
<h2>Procedure Definition</h2>
<p>Procedures are defined using a syntax similar to standard SQL <code>CREATE PROCEDURE</code>, but they include special <strong>IN</strong> and <strong>OUT</strong> parameters to handle PHP data mapping.</p>
<pre><code>PROCEDURE getAll(
		IN product_id INT,
		IN slug CHAR,
		IN language_id INT,
		OUT fetch_row, 
		OUT fetch_all, 
		OUT fetch_one,
		OUT insert_id,
		OUT affected_rows
	)
	BEGIN
	END
</code></pre>
<h3>Parameter Types</h3>
<table class="table">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IN</strong></td>
<td>Input variables passed from PHP (e.g., <code>INT</code>, <code>CHAR</code>, <code>ARRAY</code>).</td>
</tr>
<tr>
<td><strong>OUT</strong></td>
<td>Defines the return format of the query results.</td>
</tr>
</tbody>
</table>
<h3>Output Types (OUT)</h3>
<ul>
<li><code>fetch_all</code>: Returns an array of all matching rows.</li>
<li><code>fetch_row</code>: Returns a single associative array (for <code>LIMIT 1</code>).</li>
<li><code>fetch_one</code>: Returns a single scalar value (e.g., a count or a specific column).</li>
<li><code>insert_id</code>: Returns the ID generated by the last <code>INSERT</code> statement.</li>
<li><code>affected_rows</code>: Returns the number of rows modified by <code>UPDATE</code> or <code>DELETE</code>.</li>
</ul>
<hr />
<h2>SQL Example (product.sql)</h2>
<pre><code class="language-sql">
-- Products

	-- get one product

	CREATE PROCEDURE get(
		IN product_id INT,
		IN slug CHAR,
		OUT fetch_row 
	)
	BEGIN
		-- product
		SELECT *
			FROM product as _ -- (underscore) _ means that data will be kept in main array
		WHERE 1 = 1 

		@IF isset(:product_id)
		THEN
			AND product_id = :product_id
		END @IF				
		
		@IF isset(:slug)
		THEN
			AND slug = :slug
		END @IF	

		LIMIT 1;	

	END
	

	-- Edit product

	CREATE PROCEDURE edit(
		IN product ARRAY,
		IN product_id INT,
		OUT affected_rows
	)
	BEGIN

		-- SELECT * FROM product_option WHERE product_id = :product_id;

		-- allow only table fields and set defaults for missing values
		@FILTER(:product, product);
		
		UPDATE product 
			
			SET @LIST(:product) 
			
		WHERE product_id = :product_id
	END	


	-- Add new product

	CREATE PROCEDURE add(
		IN product ARRAY,
		IN site_id INT,
		OUT insert_id,
		OUT insert_id
	)
	BEGIN
		
		-- allow only table fields and set defaults for missing values
		:product  = @FILTER(:product, product);

		INSERT INTO product 
		
			( @KEYS(:product) )
			
		VALUES ( :product );
		
		INSERT INTO product_to_site 
		
			( product_id, site_id )
			
		VALUES ( @result.product, :site_id );
			

	END


	-- get all products 

	CREATE PROCEDURE getAll(

		-- variables
		IN  language_id INT,
		IN  user_group_id INT,
		IN  site_id INT,
		IN  search CHAR,
		
		-- pagination
		IN  start INT,
		IN  limit INT,
			
		-- return array of products for products query
		OUT fetch_all,
		-- return products count for count query
		OUT fetch_one,
	)
	BEGIN

		SELECT * FROM product AS product
		
			LEFT JOIN product_to_site p2s ON (product.product_id = p2s.product_id) 
			WHERE p2s.site_id = :site_id

			@IF isset(:search)
			THEN 
			
				AND name LIKE :search
				
			END @IF			
			
		LIMIT :start, :limit;


		SELECT count(*) FROM (
			
			@SQL_COUNT(product.product_id, product) -- this takes previous query removes limit and replaces select columns with parameter product_id
			
		) as count;


	END


	-- delete product

	CREATE PROCEDURE delete(
		IN  product_id ARRAY,
		OUT affected_rows
	)
	BEGIN

		DELETE FROM product WHERE product_id IN (:product_id)
	 
	END
</code></pre>
<p>Will generate a file <code>productsql.mysqli.php</code> with the following structure:</p>
<pre><code class="language-php">&lt;?php 

/*
Generated from /home/www/vvveb/vvveb/admin/sql/mysqli//product.sql
*/
namespace Vvveb\Sql;

use \Vvveb\System\Db;

class ProductSQL {
	
	function get($params = array()) {
	}		
	
	function edit($params = array()) {
	}		
	
	
	function add($params = array()) {
	}		
	
	function getAll($params = array()) {
	}		
	
	function delete($params = array()) {
	}		

}
</code></pre>
<h2>PHP Usage</h2>
<p>Once the <code>.sql</code> file is saved, use the generated class in your PHP code:</p>
<pre><code class="language-php">use Vvveb\Sql\ProductSQL;

$db = new ProductSQL();

// Fetch data (returns array/object based on OUT param)
$product = $db-&gt;get(['product_id' =&gt; 3]);

// Get first 3 products
$data = $product-&gt;getAll(['limit' =&gt; 3);

// Insert data
$newId = $db-&gt;add([
    'product' =&gt; ['name' =&gt; 'New Camera', 'price' =&gt; 599],
    'site_id' =&gt; 1
]);

//edit product with product_id = 1
$product-&gt;edit(['product' =&gt; ['name' =&gt; 'Product 2', 'price' =&gt; 100], 'product_id' =&gt; 1]);

//delete product with product_id = 3
$data = $product-&gt;delete(['product_id' =&gt; 3);

</code></pre>
<h2>Macros</h2>
<p>SqlP uses custom macros to handle dynamic logic directly within the SQL file.</p>
<h3>1. Logic Macros (<code>@IF</code>, <code>@ELSE</code>)</h3>
<h3>If macro</h3>
<pre><code class="language-sql">@IF isset(:product_id)
THEN
	AND product_id = :product_id
END @IF		
</code></pre>
<p>With @IF you can conditionally include sql code, the condition is valid <strong>native PHP code</strong>, you can use any php code with multiple conditions or different functions like</p>
<pre><code class="language-php">@IF isset(:product_id) AND !empty(:product_id)
</code></pre>
<h3>If else macro</h3>
<pre><code class="language-sql">@IF isset(:product_id)
THEN
	AND product_id = :product_id
@ELSE
	AND product_id = 0
END @IF		
</code></pre>
<p>With @IF @ELSE macro</p>
<pre><code class="language-php">@IF isset(:product_id) AND !empty(:product_id)
</code></pre>
<h3>2. Helper Macros</h3>
<ul>
<li><strong><code>@SQL_COUNT(col, table)</code></strong>: Automatically generates a count query based on the preceding <code>SELECT</code> statement, removing limits and optimizing columns.</li>
<li><strong><code>@LIST(:array)</code></strong>: Expands an array into <code>col1=val1, col2=val2</code> (ideal for <code>UPDATE</code>).</li>
<li><strong><code>@KEYS(:array)</code></strong>: Returns a comma-separated list of array keys (ideal for <code>INSERT</code>).</li>
<li><strong><code>@SQL_LIMIT(:start, :limit)</code></strong>: Handles cross-database syntax differences for pagination.</li>
</ul>
<h3>SQL_COUNT</h3>
<p>Use this macro to run sql count for the previous query to avoid duplicating the query code.
The macro will automatically replace all the columns (product_id, name) from the query with the first parameter products.product_id, the second parameter is the table name.</p>
<pre><code class="language-sql">	SELECT product_id, name FROM products 
		INNER JOIN product_content pc ON pc.product_id = product.product_id
	WHERE vendor_id = 1; 

	SELECT count(*) FROM (
		
		@SQL_COUNT(products.product_id, product) -- this takes previous query removes limit and replaces select columns with parameter product_id
		
	) as count;
</code></pre>
<h3>LIST</h3>
<p>Will expand the array into a column=value list in the format used by UPDATE queries.</p>
<pre><code class="language-sql">column1=value, column2=value2, column3=value3
</code></pre>
<pre><code class="language-sql">UPDATE product 
	SET @LIST(:product_update) 
</code></pre>
<h3>3. Loop Macro (<code>@EACH</code>)</h3>
<h3>EACH</h3>
<p>Repeats a query for every item in a PHP array, :each is the item in the array</p>
<pre><code class="language-sql">@EACH(:product_digital_asset) 
	INSERT INTO  product_to_digital_asset 

		( digital_asset_id, product_id)
	
	VALUES ( :each, :product_id );

-- example with KEYS macro

@EACH(:product_attribute) 
	INSERT INTO product_attribute 

		( @KEYS(:each), product_id)
	
	VALUES ( :each, :product_id );
</code></pre>
<h3>KEYS</h3>
<p>Keys macro will use the key instead of value for array values similar to php <code>array_keys</code>
In the following example</p>
<pre><code class="language-sql">@EACH(:product_attribute) 
	INSERT INTO product_attribute 

		( @KEYS(:each), product_id)
	
	VALUES ( :each, :product_id );
</code></pre>
<pre><code class="language-php">$product_attribute = [1 =&gt; ['name' =&gt; 'Product 1', 'price' =&gt; 30], 2 =&gt; 'Product 2', 'price' =&gt; 50];
</code></pre>
<p>:each will be</p>
<pre><code class="language-php">'Product 1', '30'
</code></pre>
<p>and @KEYS(:each) will be</p>
<pre><code class="language-sql">'name', 'price'
</code></pre>
<h3>SQL limit</h3>
<p>Use this macro to avoid LIMIT syntax differences between pgsql and mysql</p>
<pre><code class="language-sql">@IF isset(:limit)
THEN
	@SQL_LIMIT(:start, :limit)
END @IF;		
</code></pre>
<h2>array_key and array_value column alias</h2>
<p>With <code>array_key</code> and <code>array_value</code> column aliases you can change the format of the returned results to be more compact.
Use these aliases to return custom associative arrays instead of standard nested lists.</p>
<p>For example</p>
<pre><code class="language-sql">-- stock status	
SELECT 

	stock_status_id
	name
	
FROM stock_status as stock_status_id;
</code></pre>
<p>will return</p>
<pre><code class="language-php">['stock_status_id' =&gt; 
	[	
		0 =&gt; ['stock_status_id' =&gt; 5, 'name' =&gt; 'status 1' ],
		1 =&gt; ['stock_status_id' =&gt; 8, 'name' =&gt; 'status 2' ],
		2 =&gt; ['stock_status_id' =&gt; 9, 'name' =&gt; 'status 3' ]
	]
];		
</code></pre>
<p>with the aliases</p>
<pre><code class="language-sql">-- stock status	
SELECT 

	stock_status_id as array_key, -- stock_status_id as key
	name as array_value -- only set name as value and return  
	
FROM stock_status as stock_status_id;
</code></pre>
<p>the return data will be</p>
<pre><code class="language-php">['stock_status_id' =&gt; 
	[	
		5 =&gt; 'status 1',
		8 =&gt; 'status 2',
		9 =&gt; 'status 3'
	]
];		
</code></pre>
<p>with only <code>array_key</code> alias</p>
<pre><code class="language-sql">-- stock status	
SELECT 

	stock_status_id as array_key, -- stock_status_id as key
	name
	
FROM stock_status as stock_status_id;
</code></pre>
<p>the return data will be</p>
<pre><code class="language-php">['stock_status_id' =&gt; 
	[	
		5 =&gt; ['stock_status_id' =&gt; 5, 'name' =&gt; 'status 1' ],
		8 =&gt; ['stock_status_id' =&gt; 8, 'name' =&gt; 'status 2' ],
		9 =&gt; ['stock_status_id' =&gt; 9, 'name' =&gt; 'status 3' ]
	]
];		
</code></pre>
<hr />
<h2>Result Formatting &amp; Aliases</h2>
<h2>_ table alias</h2>
<p>By default, SqlP wraps results in an array keyed by the {table name}. Use the <code>_</code> alias to flatten the result.</p>
<ul>
<li><strong>Standard:</strong> <code>['product' =&gt; ['name' =&gt; 'Phone']]</code></li>
<li><strong>With <code>AS _</code>:</strong> <code>['name' =&gt; 'Phone']</code></li>
</ul>
<p>For example with</p>
<pre><code class="language-sql">-- select example

-- product
SELECT product.*
	FROM product
WHERE product.vendor_id = 1 LIMIT 1;		
</code></pre>
<p>The values will be returned in the array using the table name for array key</p>
<pre><code class="language-php">['product' =&gt; [ 
		['name' =&gt; 'product 1], 
		['name' =&gt; 'product 2], 
	]
]
</code></pre>
<p>With the _ alias</p>
<pre><code class="language-sql">-- select example

-- product
SELECT product.*
	FROM product
WHERE product.vendor_id = 1 LIMIT 1;		
</code></pre>
<p>The values will be returned without the table name as key and the values will be appended to the array directly</p>
<pre><code class="language-php">[ 
	['name' =&gt; 'product 1], 
	['name' =&gt; 'product 2], 
]
</code></pre>
<h2>@result.table_name</h2>
<p>When you need to use a value from a previous query like a last_insert id or a column id you can use @result.table_name</p>
<p>Access data from a previous query within the same procedure.</p>
<ul>
<li><code>@result.table_name</code>: Returns the last insert ID or row from that table.</li>
<li><code>@result.column_name</code>: If using the <code>_</code> alias, access the column value directly.</li>
</ul>
<pre><code class="language-sql">-- select example

-- product
SELECT product.*
	FROM product
WHERE product.vendor_id = 1 LIMIT 1;		

-- subscription
SELECT product_subscription.*
	FROM product_subscription
WHERE product_subscription.product_id = @result.product;		


-- insert example

-- product

INSERT INTO product 

	( @KEYS(:product_data) )
	
VALUES ( :product_data );

-- subscription
SELECT product_subscription.*
	FROM product_subscription
WHERE product_subscription.product_id = @result.product;		
</code></pre>
<p>When you use <code>_</code> for table name alias because values are in the top level array you can use @result.column_name directly</p>
<pre><code class="language-sql">-- select example

-- product
SELECT product.*
	FROM product AS _
WHERE product.vendor_id = 1 LIMIT 1;		

-- subscription
SELECT product_subscription.*
	FROM product_subscription
WHERE product_subscription.product_id = @result.product_id;		
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="130">
			<title data-v-post-name="name">Theme introduction</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/theme-introduction</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Themes are made of plain html files, any static html site is a valid Vvveb theme. 
Themes are located in public/themes/my-theme-name 
For pages like post or product to properly load the correct html f]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Themes are made of plain html files, any static html site is a valid Vvveb theme.</p>
<p>Themes are located in <code>public/themes/my-theme-name</code></p>
<p>For pages like post or product to properly load the correct html file, you need to properly name and group your html files in the following structure.</p>
<h3>Folder and files structure</h3>
<ul>
<li>├── <strong>index.html</strong>  - default template used for homepage</li>
<li>├── <strong>index.coming-soon.html</strong>  - homepage when site is set to coming soon</li>
<li>├── <strong>index.maintenance.html</strong>  - homepage when site is set to maintenance</li>
<li>├── <strong>error404.html</strong>  - page not found error page</li>
<li>├── <strong>error500.html</strong>  - internal server error page</li>
<li>├── <strong>blank.html</strong>  - page with basic layout with minimal or no content</li>
<li>└── content
<ul>
<li>└── <strong>index.html</strong> - blog page</li>
<li>└── <strong>post.html</strong> - singe post page</li>
<li>└── <strong>page.html</strong> - page template</li>
<li>└── <strong>tag.html</strong> - posts list for tag</li>
<li>└── <strong>category.html</strong> - posts lists for category</li>
<li>└── <strong>archive.html</strong> - posts list for a certain date</li>
<li>└── <strong>user.html</strong> - posts list by user (author)</li>
</ul>
</li>
<li>└── product
<ul>
<li>└── <strong>index.html</strong> - shop page</li>
<li>└── <strong>product.html</strong> - singe product page</li>
<li>└── <strong>manufacturer.html</strong> - manufacturer page</li>
<li>└── <strong>vendor.html</strong> - vendor page</li>
<li>└── <strong>category.html</strong> - category page</li>
</ul>
</li>
<li>└── search
<ul>
<li>└── <strong>search.html</strong> - search page</li>
</ul>
</li>
<li>└── user
<ul>
<li>└── <strong>index.html</strong> - user dashboard</li>
<li>└── <strong>signup.html</strong> - user signup form</li>
<li>└── <strong>login.html</strong> - site login form</li>
<li>└── <strong>reset.html</strong> - password reset form</li>
<li>└── <strong>edit.html</strong> - user data edit</li>
<li>└── <strong>address.html</strong> - address list</li>
<li>└── <strong>comments.html</strong> - comments list</li>
<li>└── <strong>orders.html</strong> - orders list</li>
<li>└── <strong>downloads.html</strong> - digital products downloads list</li>
</ul>
</li>
<li>└── cart
<ul>
<li>└── <strong>cart.html</strong> - display cart page</li>
</ul>
</li>
<li>└── checkout
<ul>
<li>└── <strong>checkout.html</strong> - cart checkout form</li>
<li>└── <strong>confirm.html</strong> - order confirmation page</li>
</ul>
</li>
<li>└── email
<ul>
<li>└── order
<ul>
<li>└── <strong>new.html</strong> - template for new order mail</li>
<li>└── <strong>new.html.txt</strong> - text template for new order mail</li>
</ul>
</li>
<li>└── user
<ul>
<li>└── <strong>reset.html</strong> - template for new order mail</li>
<li>└── <strong>reset.html.txt</strong> - text template for new order mail</li>
<li>└── <strong>signup.html</strong> - template for user welcome</li>
<li>└── <strong>signup.html.txt</strong> - text template for user welcome</li>
</ul>
</li>
</ul>
</li>
</ul>
<details>
<summary>Structure text</summary>
<p>
<pre><code class="language-bash">
├── index.html  -- **default template used for homepage**
├── index.coming-soon.html  -- *replaces homepage when site is set to coming soon*
├── index.maintenance.html  -- replaces homepage when site is set to maintenance
├── error404.html  -- page not found error page
├── error500.html  -- internal server error page
├── blank.html  -- page with basic layout with minimal or no content
└── content
│   └── index.html - blog page
│   └── post.html - singe post page
│   └── page.html - page template
│   └── tag.html - posts for tag page
│   └── category.html - posts category page
│   └── archive.html - posts for a certain date
│   └── user.html - user posts
└── product 
│   └── index.html - shop page
│   └── product.html - singe product page
│   └── manufacturer.html - manufacturer page
│   └── vendor.html - vendor page
│   └── category.html - category page
└── search 
│   └── search.html - search page
└── user
│   └── index.html - user dashboard
│   └── signup.html - user signup form
│   └── login.html - site login form
│   └── reset.html - password reset form
│   └── edit.html - user data edit
│   └── address.html - address list
│   └── comments.html - comments list
│   └── orders.html - orders list
│   └── downloads.html - digital products downloads list
└── cart 
│   └── cart.html - display cart page
└── checkout 
│   └── checkout.html - cart checkout form
│   └── confirm.html - order confirmation page
│   └── confirm.html - order confirmation page
└── email
│   └── order
│   │	└── new.html - template for new order mail
│   │	└── user
│   └── reset.html - template for new order mail
   	└── signup.html - template for user welcome

</code></pre>
</p>
</details>
<p>In addition to default templates your theme can provide additional template for users to choose.</p>
<p>For example you can have multiple product or posts templates for different layouts like large hero header or template for events like black friday etc.</p>
<p>Users can choose different templates for a certain post or product or choose a different template for homepage.</p>
<p>You can easily convert your html mockup into a theme in just a few minutes.</p>
<h3>Components</h3>
<p>Components are page elements that define a certain area in the template either for editing in the page builder or to define dynamic content.</p>
<p>They are defined by adding a data attribute to a html element.</p>
<p>Static components are defined with <code>data-component-name</code> and dynamic components are defined with <code>data-v-component-name</code>.</p>
<p>Examples:</p>
<pre><code class="language-html">&lt;div data-component-video&gt;This element will be edited as a video element by the page builder&lt;/div&gt;
&lt;div data-v-component-products&gt;This element will display products from database&lt;/div&gt;
</code></pre>
<h4>Static components</h4>
<p>Static components are used to designate elements that are recognized by the page builder.</p>
<p>You can use existing components in your theme or you can create your own components to edit elements like testimonials, sliders etc.</p>
<p>For a list of existing components and how to add new ones check the <a href="https://github.com/givanz/VvvebJs/wiki/Components">Components guide</a></p>
<h4>Dynamic components</h4>
<p>Dynamic components are used to display content from the database like posts, products, cart, user info etc.</p>
<p>In addition to component <code>data-v-component-posts</code> attribute, you can also define attributes for component properties like post name <code>data-v-post-name</code> or image  <code>data-v-post-image</code>.</p>
<p>For example to display a list of the latest 3 posts in a template you can use the following snippet.</p>
<pre><code class="language-html">&lt;div class=&quot;container&quot; data-v-component-posts data-v-limit=&quot;3&quot;&gt;      
	&lt;div class=&quot;row&quot;&gt;
        &lt;div class=&quot;col-12 col-lg-4 mb-2&quot; data-v-post&gt;

          &lt;article class=&quot;card&quot;&gt;
			&lt;div class=&quot;card-img-top&quot;&gt;
              &lt;img src=&quot;/media/posts/6.jpg&quot; data-v-post-image&gt;
             &lt;/div&gt;
            
            &lt;div class=&quot;card-body&quot;&gt;
              &lt;div class=&quot;post-title card-title&quot;&gt;
                &lt;a href=&quot;/hello-world-6&quot; data-v-post-url&gt;
                  &lt;h3 data-v-post-name &gt;Mauris viverra cursus ante laoreet eleifend&lt;/h3&gt;
                &lt;/a&gt;
              &lt;/div&gt;
              
              &lt;p class=&quot;card-text text-muted&quot; data-v-post-excerpt&gt;
				Et et saepe suscipit debitis a accusamus nulla in amet molestiae voluptates dolor autem vitae optio ipsa mollitia voluptatem vitae.
			  &lt;/p&gt;
			  
              &lt;a href=&quot;/hello-world-6&quot; data-v-post-url&gt;
                &lt;span&gt;Read more&lt;/span&gt;
              &lt;/a&gt;
            &lt;/div&gt;
          &lt;/article&gt;
	
		&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>For a complete list of components and specific attributes check the <a href="https://github.com/givanz/VvvebJs/wiki/Components">Components list</a></p>
<h3>Theme configuration</h3>
<p>Theme configuration is optional and is done by having a <code>theme.php</code> file in the root of the theme folder.</p>
<p>This file is used to define additional theme information like theme autor, theme homepage url, or to override some template names or add better names for new templates added by the theme.</p>
<pre><code class="language-php">&lt;?php
/*
Name: Landing
Slug: landing
URI: https://vvveb.com
Author: Vvveb
Author URI: https://vvveb.com
Description: Default theme
Version: 2.0
License:  Apache 2.0
License URI: https://vvveb.com/licence/
Tags: blog, ecommerce
Text Domain: landing
*/
use function Vvveb\__;

return
	[
		'pages' =&gt; [
			'index' =&gt; [
				'name'        =&gt; 'index',
				'file'        =&gt; 'index.html',
				'url'         =&gt; '/themes/landing/index.html',
				'title' =&gt;  __('Home page title defined from theme config'),
				'folder'      =&gt; '',
				'description' =&gt; __('Website homepage'),
			],
			'contact' =&gt; [
				'name'        =&gt; 'contact',
				'file'        =&gt; 'contact.html',
				'url'         =&gt; '/themes/landing/contact.html',
				'title' =&gt;  __('Contact us page'),
				'folder'      =&gt; '',
				'description' =&gt; __('Contact us page'),
		]			
		'ignoreFolders' =&gt; ['theme-demo-data'],//add additional folders to ignore for page builder when loading template list
		'plugins' =&gt; [
			'required' =&gt;  ['contact-form']
			'recommended' =&gt;  ['markdown-editor']
		]
	];

</code></pre>
<h3>Editor support</h3>
<p>To add custom components, sections or blocks when the theme is edited in the page builder you need to have a folder for each in your theme root folder.</p>
<pre><code class="language-bash">└── my-theme
│   └── sections
│  	 └── sections.js - javascript code that adds custom components
│   └── blocks
│  	 └── blocks.js - javascript code that adds custom blocks
│   └── inputs
│  	 └── inputs.js - javascript code that adds custom inputs
│   └── js
│  	 └── vvvebjs.js - javascript code that is executed after the editor is loaded, use it to hook to events. 
					  For example the default landing theme uses it to remove navbar sticky classes on page saving.
					  https://github.com/givanz/landing/blob/main/js/vvvebjs.js
</code></pre>
<h2>Child themes</h2>
<p>Child themes are themes that override parts of a parent theme.</p>
<p>They are used to make new themes that have some small differences from parent theme to avoid duplication and repetition of parent html for easier maintenance and development.</p>
<p>The most common use is to replace a certain part of a template from parent or a whole page or just include some additional css or javscript.</p>
<h3>Replacing template parts</h3>
<p>If you want your child theme to have a different homepage but keep the navigation and footer from parent theme you can define the following html as <em>child-theme/index.html</em>:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;base href=&quot;&quot;&gt;
	&lt;title&gt;Child theme hompepage&lt;/title&gt;
	&lt;!-- include parent styles from parent css folder --&gt;
	&lt;link href=&quot;../landing/css/style.bundle.css&quot; rel=&quot;stylesheet&quot;&gt;
	&lt;!-- add child theme styles from current folder --&gt;
	&lt;link href=&quot;css/style.css&quot; rel=&quot;stylesheet&quot;&gt;
&lt;head&gt;
&lt;body&gt;

&lt;nav data-v-copy-from=&quot;../landing/blank.html,body &gt; nav:first&quot;&gt;test&lt;/nav&gt;
	
	&lt;main&gt;
		&lt;h1&gt;Child theme content&lt;/h1&gt;
	&lt;/main&gt;

&lt;footer data-v-copy-from=&quot;../landing/blank.html,footer&quot;&gt;&lt;/footer&gt;

&lt;script id=&quot;jquery-js&quot; src=&quot;../landing/js/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script id=&quot;landing-js&quot; src=&quot;../landing/js/theme.js&quot;&gt;&lt;/script&gt;
&lt;script id=&quot;child-theme-js&quot; src=&quot;js/theme.js&quot;&gt;&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><code>data-v-copy-from</code> attribute is used to replace the tag where the attribute is defined with the content that is specified as value.</p>
<p>The synax is <code>path/to/html-template.html,#css-selector &gt; .element</code> the path is relative to the current html file and can point to child templates or any parent theme by using <code>../parent-theme/</code> in the path.</p>
<p>You can override any parent template like <em>content/post.html</em> or <em>product/product.html</em> using the same pattern as in the above example.</p>
<h2>Advanced features</h2>
<p>If you have some specific needs that are not covered by the default implementation of current components or you need to tweak the way they work then you can override the components code by providing custom template files.
You need to include your templates in a <code>template</code> folder that has the following structure.</p>
<ul>
<li>└── template
<ul>
<li>└── <strong>common.tpl</strong> - global template</li>
<li>└── components
<ul>
<li>└── <strong>posts.tpl</strong> - override posts component template</li>
</ul>
</li>
<li>└── content
<ul>
<li>└── <strong>post.tpl</strong> - override singe post page</li>
</ul>
</li>
<li>└── product
<ul>
<li>└── <strong>product.tpl</strong> - override single product page</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>Templating</h3>
<p>Templating in Vvveb is done with <a href="https://github.com/givanz/vtpl">Vtpl php template engine</a> you can learn more about <code>.tpl</code> files syntax in the <a href="/vtpl">vtpl documentation</a></p>
<h3>Custom dynamic components</h3>
<p>To add custom dynamic components to your theme you need to develop a plugin that you can include in your required plugins section in your <code>theme.php</code> configuration file.</p>
<p>Developing plugins is very easy check out the <a href="/plugin-introduction">plugin development guide</a></p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="131">
			<title data-v-post-name="name">Vtpl a different php template engine</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/vtpl</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Unlike most template engines that work by editing html code and inserting pieces of code or variables Vtpl uses css selectors to specify where to insert php code or variables into the html code with t]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Unlike most template engines that work by editing html code and inserting pieces of code or variables Vtpl uses css selectors to specify where to insert php code or variables into the html code with the goal to keep the html clean and untouched so you don't end up with html interwinded with php or other template language logic, keeping things clean and separate increases maintainability.</p>
<p>Vtpl templates are just lists of php code and variable names to insert into html, to specify the elements where to insert the code css selectors are used.</p>
<p>With Vtpl when the frontend template design of your app is changed you don’t have to change anything, the logic for the html file will be automatically applied for these new html files.</p>
<p>Vtpl ensures proper separations of concerns, the frontend logic is separated from presentation.</p>
<p>Vtpl makes it possible to build CMS's like <a href="https://www.vvveb.com">Vvveb</a> where any html page of the CMS can be changed to the last element without affecting the rendering of dynamic content from the database.</p>
<h2>Documentation</h2>
<p>Vtpl is just a list of <code>key = value</code> pairs.</p>
<p>On the left you need to specify the CSS selector and on the right the code that must be inserted for the selector.</p>
<p>The code to be inserted can be one of the following</p>
<h5>Simple strings</h5>
<pre><code>div#id &gt; span.class a = &quot;lorem ipsum&quot;
</code></pre>
<h5>Php variables</h5>
<pre><code class="language-css">div#id &gt; span.class a = $variable

</code></pre>
<h5>Php code for complex logic</h5>
<pre><code class="language-css">div#id &gt; span.class a = &lt;?php if ($var) echo $var;?&gt;
</code></pre>
<blockquote>
<p><strong>Note</strong>
It's a good practice to use a standard for the css selectors, for example use data attributes like <code>[data-product-name]</code> instead of generic id's or css classes.</p>
</blockquote>
<h5>Include external html sections for better reuse by using <code>from</code></h5>
<pre><code class="language-css">/*
from, a special command that copies html from other templates,
useful to include up to date html code into all templates from the currently maintained template 
for the specified section a common use is to apply the header from homepage to all other other html templates
*/

div#top &gt; div.header = from(homepage.html|div#top &gt; div.header)

/*
Or you can skip the selector part, in this case the same selector (eg div#top &gt; div.header) is assumed.
*/
div#top &gt; div.header = from(homepage.html)

</code></pre>
<h2>List of modifiers</h2>
<h5>innerHTML</h5>
<pre><code class="language-css">/*
by default code is inserted into the specified elements without replacing the current elements (innerHTML) 
to replace the entire elements with the specified code use outerHTML modifier
*/

div#id &gt; span.class a|innerHTML = &quot;lorem ipsum&quot;
</code></pre>
<h5>Before</h5>
<pre><code class="language-css">/*
Inserts the code before the element(s)
*/
div#id &gt; span.class a|before = &quot;lorem ipsum&quot;

</code></pre>
<h5>Prepend</h5>
<pre><code class="language-css">/*
Inserts the code at the beginning inside the element(s)
*/
div#id &gt; span.class a|prepend = &quot;lorem ipsum&quot;

</code></pre>
<h5>After</h5>
<pre><code class="language-css">/*
Inserts the code after the element(s)
*/
div#id &gt; span.class a|after = &quot;lorem ipsum&quot;

</code></pre>
<h5>Append</h5>
<pre><code class="language-css">/*
Inserts the code at the end in the element(s)
*/
div#id &gt; span.class a|append = &quot;lorem ipsum&quot;
</code></pre>
<h5>deleteAllButFirst</h5>
<pre><code class="language-css">/* Deletes all elements for the specified selector except for the first elements, usually in mockups front end developers add multiple elements to better show the final page look, the programmer just needs one element to iterate and fill data*/
div#id &gt; span.class a|deleteAllButFirst

/*

&lt;!-- this --&gt;
&lt;div id=&quot;id&quot;&gt;
&lt;span class=&quot;class&quot;&gt;
&lt;a&gt;link 1&lt;/a&gt;
&lt;a&gt;link 2&lt;/a&gt;
&lt;a&gt;link 3&lt;/a&gt;
&lt;/span&gt;
&lt;/div

**wil result into this**

&lt;div id=&quot;id&quot;&gt;
&lt;span class=&quot;class&quot;&gt;
&lt;a&gt;link 1&lt;/a&gt;
&lt;/span&gt;
&lt;/div&gt;
*/
</code></pre>
<h4>hide</h4>
<pre><code class="language-css">/*removes the specified elements if the variable ($articles) is false*/
div.articles|if_exists = $articles
</code></pre>
<h4>delete</h4>
<pre><code class="language-css">/* removes the specified elements*/
div.articles|delete
</code></pre>
<h4>attributes</h4>
<pre><code class="language-css">attributes
/*
to inject code into a tag's attribute you must specify the attribute as an modifier
*/
div#id &gt; span.class a|href = &quot;www.thewebsite.com&quot;

div#id &gt; span.class a|title = &quot;The website&quot;
</code></pre>
<h2>Additional commands</h2>
<h4>Import</h4>
<p>Includes additional files, usefull to separate logic when things get bigger and harder to maintain in one file</p>
<pre><code class="language-css">import(profile/activity_tab.tpl)
</code></pre>
<h2>Comments</h2>
<p>Vtpl can have comments</p>
<pre><code> //single line  
 /* Or multiple line  
 comments  
 */  
</code></pre>
<h2>Debugging</h2>
<pre><code class="language-css">/*
just on some portions with the following directive directly into the Vtpl files
/*
you can turn on debug with
*/
debug = true
/*
or turn it off with
*/
debug = false
</code></pre>
<p>When in debug mode, you will have a list of all template injections made on the html to visualize.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="132">
			<title data-v-post-name="name">Developer documentation</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/developer-documentation</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Vvveb is an open‑source CMS built in PHP with a powerful visual page builder and support for MySQL, PostgreSQL, and SQLite. 
Its architecture follows an MVCC pattern (Model–View–Controller–Com]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Vvveb is an open‑source CMS built in PHP with a powerful visual page builder and support for MySQL, PostgreSQL, and SQLite.</p>
<p>Its architecture follows an MVCC pattern (Model–View–Controller–Component), with a distinctive approach to the <strong>Model</strong> and <strong>View</strong> layers:</p>
<p>For Models SQL code is used directly rather than abstracted away, and for View HTML templates remain clean and logic‑free without any template markup.</p>
<p>This design preserves the strengths of both languages and leads to clearer separation of concerns, easier maintenance, and faster development.</p>
<hr />
<h2>Application Structure</h2>
<p>Vvveb is organized into main applications, <strong>app</strong>, <strong>admin</strong>, <strong>rest</strong>, <strong>graphql</strong> and <strong>install</strong>, alongside shared system directories.</p>
<ul>
<li><strong>app</strong> is the public‑facing frontend that renders pages for site visitors.</li>
<li><strong>admin</strong> is the backend interface (typically accessed at <code>/admin</code>, though this path can be changed for security) used for content and site management.</li>
<li><strong>rest</strong> serve Rest API requests</li>
<li><strong>graphql</strong> serve GraphQL API requests</li>
<li><strong>install</strong> runs automatically when no database configuration exists (<code>config/db.php</code>), guiding new installations through setup.</li>
</ul>
<p>Shared directories such as <code>system</code>, <code>public</code>, <code>plugins</code>, and <code>config</code> support all applications.</p>
<hr />
<h2>Directory Layout</h2>
<p>The directory structure is designed for clarity, modularity, and maintainability:</p>
<pre><code class="language-bash">├── app
│   ├── controller          # Frontend controllers
│   ├── component           # Frontend components (PHP logic)
│   ├── template            # Frontend templates (Vtpl)
│   ├── sql                 # SQL queries for models
│   └── validate            # Validation rules
├── admin
│   ├── controller          # Admin controllers
│   ├── component           # Admin components (PHP logic)
│   ├── template            # Admin templates (Vtpl)
│   ├── sql                 # SQL queries for admin models
│   └── validate            # Validation rules
├── install
│   ├── controller          # Installer controllers
│   ├── template            # Installer templates
│   └── sql                 # Installer SQL scripts
├── plugins
│   ├── contact-form
│   └── insert-scripts
├── system                  # Core framework files
├── config
│   └── db.php              # Database configuration
├── storage
│   ├── digital_assets      # Uploaded files
│   ├── model               # Compiled model files
│   │   ├── app
│   │   ├── admin
│   │   └── install
│   ├── backup              # Backups
│   ├── sqlite              # SQLite database files
│   ├── compiled-templates  # Cached Vtpl templates
│   └── cache               # General cache
├── public
│   ├── themes              # Frontend themes
│   │   ├── landing
│   │   └── blog-default
│   ├── admin               # Admin theme
│   │   └── default
│   ├── media               # Public media files
│   ├── js                  # Public JavaScript
│   ├── page-cache          # Static page cache
│   ├── install             # Installer public assets
│   └── plugins             # Public plugin assets
│       ├── contact-form
│       └── insert-scripts
├── plugins                # Plugins fles
├── graphql                # Graphql API
├── rest                   # Rest API
└── locale                  # Language files
</code></pre>
<hr />
<h2>Architectural Principles</h2>
<h3>SQL as the Model Layer</h3>
<p>Instead of hiding SQL behind ORM abstractions, Vvveb encourages writing SQL directly in the <code>sql</code> directory. This keeps data logic explicit, predictable, and easy to optimize.</p>
<h3>HTML as the View Layer</h3>
<p>Views are pure HTML enhanced with <strong>Vtpl</strong>, a template engine that uses CSS selectors to inject dynamic content. This ensures:</p>
<ul>
<li>HTML remains clean and designer‑friendly</li>
<li>No PHP logic is mixed into templates</li>
<li>Themes can be replaced without touching backend code</li>
</ul>
<h3>Components as the Glue</h3>
<p>Components provide the dynamic data for templates. Each component has:</p>
<ul>
<li>A PHP file (<code>app/component/...</code>) that fetches data</li>
<li>A Vtpl template (<code>app/template/components/...</code>) that binds data to HTML</li>
</ul>
<p>This structure keeps logic modular and reusable.</p>
<hr />
<h2>Application Flow</h2>
<ol>
<li>
<p><strong>Request arrives</strong><br />
The router determines whether the request belongs to the frontend (<code>app</code>), backend (<code>admin</code>), restis api, graphql api or installer (<code>install</code>).</p>
</li>
<li>
<p><strong>Controller executes</strong><br />
Component services load components, run SQL queries, and prepare data.
Controller is selected for matching route (based on <code>config/app-routes.php</code>0) and run.</p>
</li>
<li>
<p><strong>Template renders</strong><br />
Vtpl inserts dynamic data into HTML using CSS selectors.</p>
</li>
<li>
<p><strong>Response is delivered</strong><br />
The final HTML is sent to the browser, optionally cached for performance.</p>
</li>
</ol>
<hr />
<h2>Development Workflow</h2>
<ul>
<li><strong>Frontend developers</strong> work in <code>public/themes/...</code> and <code>app/template/...</code>, modifying HTML and templates without touching PHP.</li>
<li><strong>Backend developers</strong> work in <code>app/controller</code>, <code>app/component</code>, and <code>app/sql</code>, writing logic and queries.</li>
<li><strong>Plugin developers</strong> extend functionality via the <code>plugins</code> directory.</li>
<li><strong>Administrators</strong> manage content through the <code>/admin</code> interface.</li>
</ul>
<p>This separation allows teams to work independently without stepping on each other’s code.</p>
<hr />
<p>Vvveb’s structure is designed to stay flexible even as a project grows.-</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="133">
			<title data-v-post-name="name">Models</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/models</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The model part in the Vvveb MVCC is made of .sql files by using SqlP 
Admin Models  
admin 
comment 
digital_asset 
length_type 
option_value 
post_content_revision 
product_option 
product_review 
re]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The model part in the Vvveb MVCC is made of .sql files by using <a href="/sqlp">SqlP</a></p>
<h2>Admin Models</h2>
<ul>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/admin.sql">admin</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/comment.sql">comment</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/digital_asset.sql">digital_asset</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/length_type.sql">length_type</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/option_value.sql">option_value</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/post_content_revision.sql">post_content_revision</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_option.sql">product_option</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_review.sql">product_review</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/region.sql">region</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/return_status.sql">return_status</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/site.sql">site</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/subscription.sql">subscription</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/tax_rate.sql">tax_rate</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/user_group.sql">user_group</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/voucher.sql">voucher</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/attribute_group.sql">attribute_group</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/country.sql">country</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/field_group.sql">field_group</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/manufacturer.sql">manufacturer</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/order_log.sql">order_log</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/post.sql">post</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_option_value.sql">product_option_value</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product.sql">product</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/return_reason.sql">return_reason</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/role.sql">role</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/stat.sql">stat</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/subscription_status.sql">subscription_status</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/tax_rule.sql">tax_rule</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/user.sql">user</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/weight_type.sql">weight_type</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/attribute.sql">attribute</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/coupon.sql">coupon</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/field.sql">field</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/menu.sql">menu</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/order.sql">order</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_attribute.sql">product_attribute</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_question.sql">product_question</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_subscription.sql">product_subscription</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/return_resolution.sql">return_resolution</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/setting_content.sql">setting_content</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/stock_status.sql">stock_status</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/taxonomy_item.sql">taxonomy_item</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/tax_type.sql">tax_type</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/user_wishlist.sql">user_wishlist</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/category.sql">category</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/currency.sql">currency</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/language.sql">language</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/option.sql">option</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/order_status.sql">order_status</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_content_revision.sql">product_content_revision</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/product_review_media.sql">product_review_media</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/region_group.sql">region_group</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/return.sql">return</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/setting.sql">setting</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/subscription_plan.sql">subscription_plan</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/taxonomy.sql">taxonomy</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/user_address.sql">user_address</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/admin/sql/mysqli/vendor.sql">vendor</a></li>
</ul>
<h2>App Models</h2>
<ul>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/attribute.sql">attribute</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/comment.sql">comment</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/coupon.sql">coupon</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/language.sql">language</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/menu.sql">menu</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/order.sql">order</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/post.sql">post</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product_option_value.sql">product_option_value</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product_review_media.sql">product_review_media</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product.sql">product</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/region.sql">region</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/review.sql">review</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/setting.sql">setting</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/subscription_plan.sql">subscription_plan</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/tax_rate.sql">tax_rate</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/user_address.sql">user_address</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/user_wishlist.sql">user_wishlist</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/category.sql">category</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/country.sql">country</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/currency.sql">currency</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/manufacturer.sql">manufacturer</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/option.sql">option</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/permission.sql">permission</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product_option.sql">product_option</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product_question.sql">product_question</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product_review.sql">product_review</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/product_subscription.sql">product_subscription</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/return_reason.sql">return_reason</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/role.sql">role</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/site.sql">site</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/subscription.sql">subscription</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/tax_type.sql">tax_type</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/user.sql">user</a></li>
<li><a href="https://github.com/givanz/Vvveb/blob/master/app/sql/mysqli/vendor.sql">vendor</a></li>
</ul>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="135">
			<title data-v-post-name="name">Component site</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-site</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Site Component exposes global site information such as the site name, logo, description, contact details, and configuration settings. It is typically used in headers, footers, sidebars, SEO blocks]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Site Component</strong> exposes global site information such as the site name, logo, description, contact details, and configuration settings. It is typically used in headers, footers, sidebars, SEO blocks, and anywhere theme code needs access to site‑level metadata.</p>
<p>Activate the component by adding:</p>
<pre><code>data-v-component-site
</code></pre>
<p>The component automatically loads the current site unless a specific site ID is provided.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for site description and meta fields</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-site_id</code></td>
<td>Site ID to load (useful in multisite setups)</td>
<td>Current site</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>All site fields are exposed through <code>data-v-site-*</code> attributes. The following tables group them by purpose for easier reference.</p>
<hr />
<h3><strong>Branding &amp; Identity</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>logo</strong></td>
<td><code>data-v-site-logo</code></td>
<td>Main site logo</td>
</tr>
<tr>
<td><strong>logo-sticky</strong></td>
<td><code>data-v-site-logo_sticky</code></td>
<td>Logo used when header becomes sticky</td>
</tr>
<tr>
<td><strong>logo-dark</strong></td>
<td><code>data-v-site-logo_dark</code></td>
<td>Logo for dark themes</td>
</tr>
<tr>
<td><strong>logo-dark-sticky</strong></td>
<td><code>data-v-site-logo_dark_sticky</code></td>
<td>Sticky version for dark themes</td>
</tr>
<tr>
<td><strong>favicon</strong></td>
<td><code>data-v-site-favicon</code></td>
<td>Favicon URL</td>
</tr>
<tr>
<td><strong>webbanner</strong></td>
<td><code>data-v-site-webbanner</code></td>
<td>Banner image used in themes</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-site-url</code></td>
<td>Base site URL</td>
</tr>
<tr>
<td><strong>full-url</strong></td>
<td><code>data-v-site-full_url</code></td>
<td>Full domain URL</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Contact &amp; Company Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>admin-email</strong></td>
<td><code>data-v-site-admin_email</code></td>
<td>Email used for system notifications (orders, signups)</td>
</tr>
<tr>
<td><strong>contact-email</strong></td>
<td><code>data-v-site-contact_email</code></td>
<td>Public contact email</td>
</tr>
<tr>
<td><strong>address</strong></td>
<td><code>data-v-site-address</code></td>
<td>Physical address</td>
</tr>
<tr>
<td><strong>phone-number</strong></td>
<td><code>data-v-site-description-phone_number</code></td>
<td>Public phone number</td>
</tr>
<tr>
<td><strong>company</strong></td>
<td><code>data-v-site-company</code></td>
<td>Company name</td>
</tr>
<tr>
<td><strong>vat-id</strong></td>
<td><code>data-v-site-vat_id</code></td>
<td>VAT/tax ID</td>
</tr>
<tr>
<td><strong>geocode</strong></td>
<td><code>data-v-site-geocode</code></td>
<td>Geolocation data (if used by theme)</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Description &amp; SEO</strong></h3>
<p>These fields come from the <code>description</code> object.</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-site-description-title</code></td>
<td>Site title</td>
</tr>
<tr>
<td><strong>description</strong></td>
<td><code>data-v-site-description-description</code></td>
<td>Site description</td>
</tr>
<tr>
<td><strong>meta-keywords</strong></td>
<td><code>data-v-site-description-meta_keywords</code></td>
<td>SEO keywords</td>
</tr>
<tr>
<td><strong>meta-description</strong></td>
<td><code>data-v-site-description-meta_description</code></td>
<td>SEO description</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Localization &amp; Formatting</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-site-language_id</code></td>
<td>Default language ID</td>
</tr>
<tr>
<td><strong>language</strong></td>
<td><code>data-v-site-language</code></td>
<td>Language code (e.g., <code>en</code>)</td>
</tr>
<tr>
<td><strong>currency_id</strong></td>
<td><code>data-v-site-currency_id</code></td>
<td>Default currency ID</td>
</tr>
<tr>
<td><strong>currency</strong></td>
<td><code>data-v-site-currency</code></td>
<td>Currency code (e.g., <code>USD</code>)</td>
</tr>
<tr>
<td><strong>timezone</strong></td>
<td><code>data-v-site-timezone</code></td>
<td>Timezone offset</td>
</tr>
<tr>
<td><strong>date_format</strong></td>
<td><code>data-v-site-date_format</code></td>
<td>Date formatting string</td>
</tr>
<tr>
<td><strong>time_format</strong></td>
<td><code>data-v-site-time_format</code></td>
<td>Time formatting string</td>
</tr>
<tr>
<td><strong>weight_type</strong></td>
<td><code>data-v-site-weight_type</code></td>
<td>Weight unit (e.g., kg)</td>
</tr>
<tr>
<td><strong>length_type</strong></td>
<td><code>data-v-site-length_type</code></td>
<td>Length unit (e.g., cm)</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Image Processing Settings</strong></h3>
<p>These settings define how images are resized across the site.</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>post_xlarge_width</strong></td>
<td><code>data-v-site-post_xlarge_width</code></td>
<td>Width for extra‑large post images</td>
</tr>
<tr>
<td><strong>post_xlarge_height</strong></td>
<td><code>data-v-site-post_xlarge_height</code></td>
<td>Height for extra‑large post images</td>
</tr>
<tr>
<td><strong>post_xlarge_method</strong></td>
<td><code>data-v-site-post_xlarge_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>post_large_width</strong></td>
<td><code>data-v-site-post_large_width</code></td>
<td>Width for large post images</td>
</tr>
<tr>
<td><strong>post_large_height</strong></td>
<td><code>data-v-site-post_large_height</code></td>
<td>Height for large post images</td>
</tr>
<tr>
<td><strong>post_large_method</strong></td>
<td><code>data-v-site-post_large_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>post_medium_width</strong></td>
<td><code>data-v-site-post_medium_width</code></td>
<td>Width for medium post images</td>
</tr>
<tr>
<td><strong>post_medium_height</strong></td>
<td><code>data-v-site-post_medium_height</code></td>
<td>Height for medium post images</td>
</tr>
<tr>
<td><strong>post_medium_method</strong></td>
<td><code>data-v-site-post_medium_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>post_thumb_width</strong></td>
<td><code>data-v-site-post_thumb_width</code></td>
<td>Thumbnail width</td>
</tr>
<tr>
<td><strong>post_thumb_height</strong></td>
<td><code>data-v-site-post_thumb_height</code></td>
<td>Thumbnail height</td>
</tr>
<tr>
<td><strong>post_thumb_method</strong></td>
<td><code>data-v-site-post_thumb_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>product_xlarge_width</strong></td>
<td><code>data-v-site-product_xlarge_width</code></td>
<td>Product image width (XL)</td>
</tr>
<tr>
<td><strong>product_xlarge_height</strong></td>
<td><code>data-v-site-product_xlarge_height</code></td>
<td>Product image height (XL)</td>
</tr>
<tr>
<td><strong>product_xlarge_method</strong></td>
<td><code>data-v-site-product_xlarge_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>product_large_width</strong></td>
<td><code>data-v-site-product_large_width</code></td>
<td>Product image width (L)</td>
</tr>
<tr>
<td><strong>product_large_height</strong></td>
<td><code>data-v-site-product_large_height</code></td>
<td>Product image height (L)</td>
</tr>
<tr>
<td><strong>product_large_method</strong></td>
<td><code>data-v-site-product_large_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>product_medium_width</strong></td>
<td><code>data-v-site-product_medium_width</code></td>
<td>Product image width (M)</td>
</tr>
<tr>
<td><strong>product_medium_height</strong></td>
<td><code>data-v-site-product_medium_height</code></td>
<td>Product image height (M)</td>
</tr>
<tr>
<td><strong>product_medium_method</strong></td>
<td><code>data-v-site-product_medium_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>product_thumb_width</strong></td>
<td><code>data-v-site-product_thumb_width</code></td>
<td>Product thumbnail width</td>
</tr>
<tr>
<td><strong>product_thumb_height</strong></td>
<td><code>data-v-site-product_thumb_height</code></td>
<td>Product thumbnail height</td>
</tr>
<tr>
<td><strong>product_thumb_method</strong></td>
<td><code>data-v-site-product_thumb_method</code></td>
<td>Resize method</td>
</tr>
<tr>
<td><strong>image_format</strong></td>
<td><code>data-v-site-image_format</code></td>
<td>Output format (e.g., webp, jpg)</td>
</tr>
<tr>
<td><strong>image_quality</strong></td>
<td><code>data-v-site-image_quality</code></td>
<td>Compression quality</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Comments Settings</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>close_comments_days_old</strong></td>
<td><code>data-v-site-close_comments_days_old</code></td>
<td>Auto‑close comments after X days</td>
</tr>
<tr>
<td><strong>thread_comments_depth</strong></td>
<td><code>data-v-site-thread_comments_depth</code></td>
<td>Maximum nested comment depth</td>
</tr>
<tr>
<td><strong>comments_per_page</strong></td>
<td><code>data-v-site-comments_per_page</code></td>
<td>Comments per page</td>
</tr>
<tr>
<td><strong>default_comments_page</strong></td>
<td><code>data-v-site-default_comments_page</code></td>
<td>Show newest or oldest first</td>
</tr>
<tr>
<td><strong>comment_order</strong></td>
<td><code>data-v-site-comment_order</code></td>
<td>Sort order (<code>asc</code> or <code>desc</code>)</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Order &amp; Invoice Settings</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>invoice_format</strong></td>
<td><code>data-v-site-invoice_format</code></td>
<td>Format string for invoice numbers</td>
</tr>
<tr>
<td><strong>order_id_format</strong></td>
<td><code>data-v-site-order_id_format</code></td>
<td>Format string for order IDs</td>
</tr>
<tr>
<td><strong>processing_status_id</strong></td>
<td><code>data-v-site-processing_status_id</code></td>
<td>Default processing status</td>
</tr>
<tr>
<td><strong>complete_status_id</strong></td>
<td><code>data-v-site-complete_status_id</code></td>
<td>Default complete status</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-component-site&gt;

    &lt;img data-v-site-logo alt=&quot;Site logo&quot;&gt;

    &lt;h1 data-v-site-description-title&gt;&lt;/h1&gt;

    &lt;p data-v-site-address&gt;&lt;/p&gt;

&lt;/div&gt;
</code></pre>
<p>This example loads the current site and displays the logo, title, and address.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="136">
			<title data-v-post-name="name">Component breadcrumb</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-breadcrumb</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The breadcrumb component generates a navigational trail that shows users where they are within your site structure. It can be placed anywhere in your theme and automatically adapts to pages, posts, pr]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>breadcrumb</strong> component generates a navigational trail that shows users where they are within your site structure. It can be placed anywhere in your theme and automatically adapts to pages, posts, products, categories, and other content types.</p>
<p>The component element must have the following HTML attribute</p>
<pre><code class="language-html">data-v-component-breadcrumb
</code></pre>
<hr />
<h2>Component Options</h2>
<p>Add any option as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>absoluteURL</strong> - Use absolute URLs instead of relative ones. Useful when sharing links externally or when working with multi‑domain setups.</li>
<li><strong>blog</strong> - When viewing blog posts or blog categories, include the main blog URL in the breadcrumb trail.</li>
<li><strong>shop</strong> - When viewing products or product categories, include the main shop URL in the breadcrumb trail.</li>
</ul>
<p>These options help you control how deep or minimal the breadcrumb structure should be.</p>
<hr />
<h2>Component Properties</h2>
<p>Each breadcrumb item is rendered inside an element marked with <code>data-v-breadcrumb-item</code>. The following properties are available for each item:</p>
<ul>
<li><strong>text</strong> - <code>data-v-breadcrumb-item-text</code> - The visible label of the breadcrumb item.</li>
<li><strong>url</strong> - <code>data-v-breadcrumb-item-url</code> - The link for the breadcrumb item. If empty, the item is displayed as plain text (typically the current page).</li>
</ul>
<p>The component repeats these properties for every breadcrumb segment, from the homepage to the current page.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;nav aria-label=&quot;breadcrumb&quot; class=&quot;text-muted text-small&quot; data-v-component-breadcrumb&gt;
  &lt;ol class=&quot;breadcrumb&quot;&gt;

    &lt;li class=&quot;breadcrumb-item&quot; data-v-breadcrumb-item&gt;
      &lt;a data-v-breadcrumb-item-url data-v-if=&quot;breadcrumb.url&quot;&gt;
        &lt;span data-v-breadcrumb-item-text&gt;Home&lt;/span&gt;
      &lt;/a&gt;
      &lt;span data-v-breadcrumb-item-text data-v-if-not=&quot;breadcrumb.url&quot;&gt;Home&lt;/span&gt;
    &lt;/li&gt;

    &lt;li class=&quot;breadcrumb-item&quot; data-v-breadcrumb-item&gt;
      &lt;a data-v-breadcrumb-item-url data-v-if=&quot;breadcrumb.url&quot;&gt;
        &lt;span data-v-breadcrumb-item-text&gt;Library&lt;/span&gt;
      &lt;/a&gt;
      &lt;span data-v-breadcrumb-item-text data-v-if-not=&quot;breadcrumb.url&quot;&gt;Library&lt;/span&gt;
    &lt;/li&gt;

    &lt;li class=&quot;breadcrumb-item active&quot; aria-current=&quot;page&quot; data-v-breadcrumb-item&gt;
      &lt;span data-v-breadcrumb-item-text&gt;Data&lt;/span&gt;
    &lt;/li&gt;

  &lt;/ol&gt;
&lt;/nav&gt;
</code></pre>
<p>This example shows a typical breadcrumb structure with conditional links: if a breadcrumb item has a URL, it is rendered as a link; otherwise, it appears as plain text (usually the current page).</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="137">
			<title data-v-post-name="name">Components overview</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/components-overview</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Components in Vvveb CMS act as dynamic data providers that connect your theme’s HTML with backend logic. They allow you to display products, posts, users, menus, carts, and many other types of conte]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<p>Components in Vvveb CMS act as dynamic data providers that connect your theme’s HTML with backend logic.
They allow you to display products, posts, users, menus, carts, and many other types of content without writing custom queries.
Each component has a PHP file that retrieves data and a template file that binds that data to HTML using the Vtpl templating engine.</p>
<hr />
<h2>How components work in a theme</h2>
<p>Components are placed directly inside your theme’s HTML using the <code>data-v-component-*</code> attribute. Inside the component, child elements use <code>data-v-*</code> bindings to display dynamic values.</p>
<pre><code class="language-html">&lt;div data-v-component-products&gt;
	&lt;div data-v-product&gt;
		&lt;span data-v-product-name&gt;Product name placeholder&lt;/span&gt;
		&lt;span data-v-product-price&gt;$100&lt;/span&gt;
	&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>When the page is rendered, the component loads the appropriate PHP logic, fetches the data, and injects it into the HTML structure.</p>
<hr />
<h2>Where component logic and templates are stored</h2>
<p>Each component has two parts:</p>
<ul>
<li>A <strong>PHP file</strong> that retrieves data from the database</li>
<li>A <strong>template file</strong> that binds the data to HTML using <a href="/vtpl">Vtpl</a> template engine</li>
</ul>
<pre><code>app/
├── components/
│   ├── products.php      ← backend logic for products component
│   ├── posts.php         ← backend logic for posts component
│   ├── cart.php          ← backend logic for cart component
│   └── ...
└── template/
    └── components/
        ├── products.tpl  ← template for products component
        ├── posts.tpl     ← template for posts component
        ├── cart.tpl      ← template for cart component
        └── ...
</code></pre>
<p>The <code>.php</code> file prepares the data, and the <code>.tpl</code> file defines how that data appears in the theme.</p>
<hr />
<h2>Template engine</h2>
<p>Component templates use the <strong>Vtpl</strong> templating engine, which allows you to:</p>
<ul>
<li>Loop through items</li>
<li>Insert variables</li>
<li>Use conditions</li>
<li>Bind dynamic values to HTML attributes</li>
</ul>
<p>This makes it easy to customize how component data appears in your theme.</p>
<hr />
<h2>Available components</h2>
<p>Vvveb CMS includes a wide range of built‑in components for e‑commerce, content, user management, navigation, and more.</p>
<ul>
<li><a href="/component-address">address</a></li>
<li><a href="/component-breadcrumb">breadcrumb</a></li>
<li><a href="/component-categories">categories</a></li>
<li><a href="/component-category">category</a></li>
<li><a href="/component-checkout">checkout</a></li>
<li><a href="/component-config">config</a></li>
<li><a href="/component-currency">currency</a></li>
<li><a href="/component-orders">orders</a></li>
<li><a href="/component-reviews">reviews</a></li>
<li><a href="/component-search">search</a></li>
<li><a href="/component-cart">cart</a></li>
<li><a href="/component-order">order</a></li>
<li><a href="/component-user">user</a></li>
<li><a href="/component-language">language</a></li>
<li><a href="/component-products">products</a></li>
<li><a href="/component-product">product</a></li>
<li><a href="/component-post">post</a></li>
<li><a href="/component-posts">posts</a></li>
<li><a href="/component-fields">fields</a></li>
<li><a href="/component-menu">menu</a></li>
<li><a href="/component-comments">comments</a></li>
<li><a href="/component-site">site</a></li>
<li><a href="/component-admin">admin</a></li>
<li><a href="/component-admins">admins</a></li>
<li><a href="/component-user">user</a></li>
<li><a href="/component-users">users</a></li>
<li><a href="/component-compare">compare</a></li>
<li><a href="/component-digital_assets">digital_assets</a></li>
<li><a href="/component-reviews">reviews</a></li>
<li><a href="/component-questions">questions</a></li>
<li><a href="/component-wishlist">wishlist</a></li>
<li>product
<ul>
<li><a href="/component-categories">categories</a></li>
<li><a href="/component-manufacturers">manufacturers</a></li>
<li><a href="/component-vendors">vendors</a></li>
<li><a href="/component-variants">variants</a></li>
<li><a href="/component-subscriptions">subscriptions</a></li>
<li><a href="/component-options">options</a></li>
<li><a href="/component-attributes">attributes</a></li>
<li><a href="/component-filters">filters</a></li>
<li><a href="/subscription-plans">subscription-plans</a></li>
</ul>
</li>
<li><a href="/component-checkout">checkout</a></li>
<li>checkout
<ul>
<li><a href="/component-payment">payment</a></li>
<li><a href="/component-shipping">shipping</a></li>
</ul>
</li>
<li>categories
<ul>
<li><a href="/component-pages">pages</a></li>
</ul>
</li>
<li>content
<ul>
<li><a href="/component-tags">tags</a></li>
<li><a href="/component-archives">archives</a></li>
<li><a href="/component-categories">categories</a></li>
</ul>
</li>
</ul>
<p>These components can be combined to build dynamic pages without writing custom backend code.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="138">
			<title data-v-post-name="name">Component order</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-order</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Order Component renders the full details of a customer order, including products, totals, billing and shipping information, payment and shipping methods, and metadata such as order status and time]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Order Component</strong> renders the full details of a customer order, including products, totals, billing and shipping information, payment and shipping methods, and metadata such as order status and timestamps.
It is typically used on order‑detail pages, customer account pages, and order‑confirmation pages.</p>
<p>Activate the component by adding:</p>
<pre><code>data-v-component-order
</code></pre>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>order_id</strong></td>
<td><code>data-v-order_id</code></td>
<td>Load an order by internal order ID. If set to <code>url</code>, the ID is taken from the GET parameter.</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>customer_order_id</strong></td>
<td><code>data-v-customer_order_id</code></td>
<td>Load an order by customer‑facing order ID (randomized for privacy). If set to <code>url</code>, it is taken from the GET parameter.</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>email</strong></td>
<td><code>data-v-email</code></td>
<td>Filter orders by customer email.</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for product names, order statuses, and descriptions.</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>image_size</strong></td>
<td><code>data-v-image_size</code></td>
<td>Product image size: <code>xlarge</code>, <code>large</code>, <code>medium</code>, <code>thumb</code>. If omitted, site settings are used.</td>
<td><code>medium</code></td>
</tr>
</tbody>
</table>
<p>These options allow the component to load the correct order based on ID, customer order ID, or email, and to adapt to multilingual or multisite setups.</p>
<hr />
<h2><strong>Order Properties</strong></h2>
<p>The component exposes a wide set of order‑level fields. These can be used to display order metadata, customer details, billing and shipping addresses, payment and shipping information, and totals.</p>
<h3><strong>General Order Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>order_id</strong></td>
<td><code>data-v-order-order_id</code></td>
<td>Internal order ID</td>
</tr>
<tr>
<td><strong>invoice_no</strong></td>
<td><code>data-v-order-invoice_no</code></td>
<td>Invoice number Eg:I-26-03-6-1-UPDQGK9B6EKP-26</td>
</tr>
<tr>
<td><strong>customer_order_id</strong></td>
<td><code>data-v-order-customer_order_id</code></td>
<td>Public order ID shown to customers  Eg:UPDQGK9B6EKP-26</td>
</tr>
<tr>
<td><strong>invoice_prefix</strong></td>
<td><code>data-v-order-invoice_prefix</code></td>
<td>Invoice prefix</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-order-site_id</code></td>
<td>Site where the order was placed</td>
</tr>
<tr>
<td><strong>site_name</strong></td>
<td><code>data-v-order-site_name</code></td>
<td>Site name</td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-order-user_id</code></td>
<td>Customer ID</td>
</tr>
<tr>
<td><strong>user_group_id</strong></td>
<td><code>data-v-order-user_group_id</code></td>
<td>Customer group ID</td>
</tr>
<tr>
<td><strong>email</strong></td>
<td><code>data-v-order-email</code></td>
<td>Customer email</td>
</tr>
<tr>
<td><strong>phone_number</strong></td>
<td><code>data-v-order-phone_number</code></td>
<td>Customer phone number</td>
</tr>
<tr>
<td><strong>order_status</strong></td>
<td><code>data-v-order-order_status</code></td>
<td>Order status (e.g., pending, processing)</td>
</tr>
<tr>
<td><strong>order_status_id</strong></td>
<td><code>data-v-order-order_status_id</code></td>
<td>Order status ID</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-order-created_at</code></td>
<td>Order creation date</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-order-updated_at</code></td>
<td>Last update date</td>
</tr>
<tr>
<td><strong>notes</strong></td>
<td><code>data-v-order-notes</code></td>
<td>Customer notes</td>
</tr>
<tr>
<td><strong>remote_ip</strong></td>
<td><code>data-v-order-remote_ip</code></td>
<td>Customer IP address</td>
</tr>
<tr>
<td><strong>forwarded_for_ip</strong></td>
<td><code>data-v-order-forwarded_for_ip</code></td>
<td>Forwarded IP (proxy)</td>
</tr>
<tr>
<td><strong>user_agent</strong></td>
<td><code>data-v-order-user_agent</code></td>
<td>Browser user agent</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Billing Address</strong></h2>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>billing_first_name</strong></td>
<td><code>data-v-order-billing_first_name</code></td>
</tr>
<tr>
<td><strong>billing_last_name</strong></td>
<td><code>data-v-order-billing_last_name</code></td>
</tr>
<tr>
<td><strong>billing_company</strong></td>
<td><code>data-v-order-billing_company</code></td>
</tr>
<tr>
<td><strong>billing_address_1</strong></td>
<td><code>data-v-order-billing_address_1</code></td>
</tr>
<tr>
<td><strong>billing_address_2</strong></td>
<td><code>data-v-order-billing_address_2</code></td>
</tr>
<tr>
<td><strong>billing_city</strong></td>
<td><code>data-v-order-billing_city</code></td>
</tr>
<tr>
<td><strong>billing_post_code</strong></td>
<td><code>data-v-order-billing_post_code</code></td>
</tr>
<tr>
<td><strong>billing_country_id</strong></td>
<td><code>data-v-order-billing_country_id</code></td>
</tr>
<tr>
<td><strong>billing_country</strong></td>
<td><code>data-v-order-billing_country</code></td>
</tr>
<tr>
<td><strong>billing_region</strong></td>
<td><code>data-v-order-billing_region</code></td>
</tr>
<tr>
<td><strong>billing_region_id</strong></td>
<td><code>data-v-order-billing_region_id</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Shipping Address</strong></h2>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>shipping_first_name</strong></td>
<td><code>data-v-order-shipping_first_name</code></td>
</tr>
<tr>
<td><strong>shipping_last_name</strong></td>
<td><code>data-v-order-shipping_last_name</code></td>
</tr>
<tr>
<td><strong>shipping_company</strong></td>
<td><code>data-v-order-shipping_company</code></td>
</tr>
<tr>
<td><strong>shipping_address_1</strong></td>
<td><code>data-v-order-shipping_address_1</code></td>
</tr>
<tr>
<td><strong>shipping_address_2</strong></td>
<td><code>data-v-order-shipping_address_2</code></td>
</tr>
<tr>
<td><strong>shipping_city</strong></td>
<td><code>data-v-order-shipping_city</code></td>
</tr>
<tr>
<td><strong>shipping_post_code</strong></td>
<td><code>data-v-order-shipping_post_code</code></td>
</tr>
<tr>
<td><strong>shipping_country_id</strong></td>
<td><code>data-v-order-shipping_country_id</code></td>
</tr>
<tr>
<td><strong>shipping_region</strong></td>
<td><code>data-v-order-shipping_region</code></td>
</tr>
<tr>
<td><strong>shipping_region_group_id</strong></td>
<td><code>data-v-order-shipping_region_group_id</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Payment Information</strong></h2>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>payment_method</strong></td>
<td><code>data-v-order-payment_method</code></td>
<td>Payment method code</td>
</tr>
<tr>
<td><strong>payment_title</strong></td>
<td><code>data-v-order-payment_title</code></td>
<td>Payment method name</td>
</tr>
<tr>
<td><strong>payment_status</strong></td>
<td><code>data-v-order-payment_status</code></td>
<td>Payment status</td>
</tr>
<tr>
<td><strong>payment_status_id</strong></td>
<td><code>data-v-order-payment_status_id</code></td>
<td>Payment status ID</td>
</tr>
<tr>
<td><strong>payment_data</strong></td>
<td><code>data-v-order-payment_data-*</code></td>
<td>Additional payment plugin data</td>
</tr>
</tbody>
</table>
<h3>Payment Data Object</h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-order-payment_data-title</code></td>
</tr>
<tr>
<td><strong>description</strong></td>
<td><code>data-v-order-payment_data-description</code></td>
</tr>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-order-payment_data-name</code></td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-order-payment_data-status</code></td>
</tr>
<tr>
<td><strong>region_id</strong></td>
<td><code>data-v-order-payment_data-region_id</code></td>
</tr>
<tr>
<td><strong>region_group_id</strong></td>
<td><code>data-v-order-payment_data-region_group_id</code></td>
</tr>
<tr>
<td><strong>payment_status_id</strong></td>
<td><code>data-v-order-payment_data-payment_status_id</code></td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-order-payment_data-sort_order</code></td>
</tr>
<tr>
<td><strong>tax_type_id</strong></td>
<td><code>data-v-order-payment_data-tax_type_id</code></td>
</tr>
<tr>
<td><strong>cost</strong></td>
<td><code>data-v-order-payment_data-cost</code></td>
</tr>
<tr>
<td><strong>base-weight</strong></td>
<td><code>data-v-order-payment_data-weight</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Shipping Information</strong></h2>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>shipping_method</strong></td>
<td><code>data-v-order-shipping_method</code></td>
<td>Shipping method code</td>
</tr>
<tr>
<td><strong>shipping_title</strong></td>
<td><code>data-v-order-shipping_title</code></td>
<td>Shipping method name</td>
</tr>
<tr>
<td><strong>shipping_description</strong></td>
<td><code>data-v-order-shipping_description</code></td>
<td>Description</td>
</tr>
<tr>
<td><strong>shipping_status</strong></td>
<td><code>data-v-order-shipping_status</code></td>
<td>Shipping status</td>
</tr>
<tr>
<td><strong>shipping_status_id</strong></td>
<td><code>data-v-order-shipping_status_id</code></td>
<td>Status ID</td>
</tr>
<tr>
<td><strong>shipping_data</strong></td>
<td><code>data-v-order-shipping_data-*</code></td>
<td>Additional shipping plugin data</td>
</tr>
</tbody>
</table>
<h3>Shipping Data Object</h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-order-shipping_data-title</code></td>
</tr>
<tr>
<td><strong>description</strong></td>
<td><code>data-v-order-shipping_data-description</code></td>
</tr>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-order-shipping_data-name</code></td>
</tr>
<tr>
<td><strong>region_id</strong></td>
<td><code>data-v-order-shipping_data-region_id</code></td>
</tr>
<tr>
<td><strong>region_group_id</strong></td>
<td><code>data-v-order-shipping_data-region_group_id</code></td>
</tr>
<tr>
<td><strong>shipping_status_id</strong></td>
<td><code>data-v-order-shipping_data-shipping_status_id</code></td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-order-shipping_data-sort_order</code></td>
</tr>
<tr>
<td><strong>tax_type_id</strong></td>
<td><code>data-v-order-shipping_data-tax_type_id</code></td>
</tr>
<tr>
<td><strong>cost</strong></td>
<td><code>data-v-order-shipping_data-cost</code></td>
</tr>
<tr>
<td><strong>base-weight</strong></td>
<td><code>data-v-order-shipping_data-weight</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Order Totals</strong></h2>
<p>Each total row is wrapped in:</p>
<pre><code>data-v-order-total
</code></pre>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>namespace</strong></td>
<td><code>data-v-total-namespace</code></td>
<td>Group: <code>tax</code>, <code>coupon</code>, <code>total</code>, etc.</td>
</tr>
<tr>
<td><strong>key</strong></td>
<td><code>data-v-total-key</code></td>
<td>Unique key (e.g., <code>tax.1</code>, <code>coupon.3</code>, <code>sub_total</code>)</td>
</tr>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-order-total-title</code></td>
<td>Label shown to the user</td>
</tr>
<tr>
<td><strong>value</strong></td>
<td><code>data-v-order-total-value</code></td>
<td>Numeric value</td>
</tr>
<tr>
<td><strong>value_formatted</strong></td>
<td><code>data-v-order-total-value_formatted</code></td>
<td>Value formatted with currency</td>
</tr>
<tr>
<td><strong>text</strong></td>
<td><code>data-v-order-total-text</code></td>
<td>Optional explanatory text</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Products List</strong></h2>
<p>Each product in the order is wrapped in:</p>
<pre><code>data-v-order-product
</code></pre>
<h3><strong>Product Properties</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-order-product-name</code></td>
<td>Product name</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-order-product-slug</code></td>
<td>Product slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-order-product-content</code></td>
<td>Full description</td>
</tr>
<tr>
<td><strong>excerpt</strong></td>
<td><code>data-v-order-product-excerpt</code></td>
<td>Short description</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-order-product-url</code></td>
<td>Product detail page URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td><code>data-v-order-product-image</code></td>
<td>Featured image</td>
</tr>
<tr>
<td><strong>images</strong></td>
<td><code>data-v-order-product-images</code></td>
<td>Gallery images</td>
</tr>
<tr>
<td><strong>quantity</strong></td>
<td><code>data-v-order-product-quantity</code></td>
<td>Quantity in order</td>
</tr>
<tr>
<td><strong>price</strong></td>
<td><code>data-v-order-product-price</code></td>
<td>Price without tax</td>
</tr>
<tr>
<td><strong>price_tax</strong></td>
<td><code>data-v-order-product-price_tax</code></td>
<td>Price including tax</td>
</tr>
<tr>
<td><strong>price_formatted</strong></td>
<td><code>data-v-order-product-price_formatted</code></td>
<td>Price formatted with currency</td>
</tr>
<tr>
<td><strong>price_tax_formatted</strong></td>
<td><code>data-v-order-product-price_tax_formatted</code></td>
<td>Price including tax, formatted</td>
</tr>
<tr>
<td><strong>old_price</strong></td>
<td><code>data-v-order-product-old_price</code></td>
<td>Price before discount</td>
</tr>
<tr>
<td><strong>old_price_tax</strong></td>
<td><code>data-v-order-product-old_price_tax</code></td>
<td>Old price including tax</td>
</tr>
<tr>
<td><strong>old_price_tax_formatted</strong></td>
<td><code>data-v-order-product-old_price_tax_formatted</code></td>
<td>Old price formatted</td>
</tr>
<tr>
<td><strong>stock_quantity</strong></td>
<td><code>data-v-order-product-stock_quantity</code></td>
<td>Units in stock</td>
</tr>
<tr>
<td><strong>stock_status</strong></td>
<td><code>data-v-order-product-stock_status_id</code></td>
<td>Stock status</td>
</tr>
<tr>
<td><strong>product_id</strong></td>
<td><code>data-v-order-product-product_id</code></td>
<td>Product ID</td>
</tr>
<tr>
<td><strong>product_variant_id</strong></td>
<td><code>data-v-order-product-product_variant_id</code></td>
<td>Variant ID</td>
</tr>
<tr>
<td><strong>has_variants</strong></td>
<td><code>data-v-order-product-has_variants</code></td>
<td>Whether product has variants</td>
</tr>
<tr>
<td><strong>add_order_url</strong></td>
<td><code>data-v-order-product-add_order_url</code></td>
<td>Add‑to‑order URL</td>
</tr>
<tr>
<td><strong>buy_url</strong></td>
<td><code>data-v-order-product-buy_url</code></td>
<td>Direct buy URL</td>
</tr>
<tr>
<td><strong>remove_url</strong></td>
<td><code>data-v-order-product-remove_url</code></td>
<td>Remove from order URL</td>
</tr>
<tr>
<td><strong>manufacturer_name</strong></td>
<td><code>data-v-order-product-manufacturer_name</code></td>
<td>Manufacturer</td>
</tr>
<tr>
<td><strong>vendor_name</strong></td>
<td><code>data-v-order-product-vendor_name</code></td>
<td>Vendor</td>
</tr>
<tr>
<td><strong>subscription_name</strong></td>
<td><code>data-v-order-product-subscription_name</code></td>
<td>Subscription plan name</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-order-product-created_at</code></td>
<td>Creation date</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-order-product-updated_at</code></td>
<td>Last update</td>
</tr>
<tr>
<td><strong>pubDate</strong></td>
<td><code>data-v-order-product-pubDate</code></td>
<td>Publish date (RSS format)</td>
</tr>
<tr>
<td><strong>modDate</strong></td>
<td><code>data-v-order-product-modDate</code></td>
<td>Modification date (RSS format)</td>
</tr>
</tbody>
</table>
<p>Product options, variants, and subscription details are also available as nested repeatables.</p>
<hr />
<h2><strong>HTML Example</strong></h2>
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-customer_order_id=&quot;url&quot; data-v-component-order&gt;

	&lt;h2&gt;Order ID: &lt;span data-v-order-customer_order_id&gt;UPDQGK9B6EKP-26&lt;/span&gt;&lt;/h2&gt;

	  &lt;table data-v-cart&gt;
		&lt;thead&gt;
		  &lt;tr&gt;
			&lt;th&gt;Image&lt;/th&gt;
			&lt;th&gt;Product Name&lt;/th&gt;
			
			&lt;th&gt;Quantity&lt;/th&gt;
			&lt;th&gt;Unit Price&lt;/th&gt;
			&lt;th&gt;Total&lt;/th&gt;
		  &lt;/tr&gt;
		&lt;/thead&gt;
		&lt;tbody&gt;
		  &lt;tr data-v-order-product data-product_id=&quot;15&quot;&gt;
			&lt;td&gt;
			  &lt;a href=&quot;http://vvveb.net/product/product-fifteen&quot; data-v-order-product-url&gt;
				&lt;img src=&quot;http://vvveb.net/image-cache/demo/products/5-1-150x0_s.jpg&quot; alt=&quot;Product name&quot; data-v-order-product-image width=&quot;50&quot; loading=&quot;lazy&quot;&gt;
			  &lt;/a&gt;
			&lt;/td&gt;
			&lt;td&gt;
			  &lt;a href=&quot;http://vvveb.net/product/product-fifteen&quot; target=&quot;_blank&quot; data-v-order-product-url&gt;
				&lt;span data-v-order-product-name&gt;Product 15&lt;/span&gt;
			  &lt;/a&gt;

			  
			  &lt;div&gt;
				&lt;span data-v-order-product-price_tax_formatted&gt;$100&lt;/span&gt;
			  &lt;/div&gt;
			&lt;/td&gt;

			
			&lt;td&gt;
			  &lt;span data-v-order-product-quantity&gt;1&lt;/span&gt;
			&lt;/td&gt;
			&lt;td&gt;
			  &lt;span data-v-order-product-price_formatted&gt;&lt;/span&gt;
			&lt;/td&gt;
			
			&lt;td&gt;
			  &lt;span data-v-order-product-tax_formatted&gt;$2,561.00&lt;/span&gt;
			&lt;/td&gt;
		  &lt;/tr&gt;             
		 &lt;/tbody&gt;

		&lt;tfoot data-v-order-totals&gt;
		  &lt;tr data-v-order-totals-total&gt;
			&lt;td colspan=&quot;4&quot;&gt;
			  &lt;small data-v-order-total-title&gt;Sub-total&lt;/small&gt;:
			&lt;/td&gt;
			&lt;td data-v-order-total-value_formatted&gt;$3,000.00&lt;/td&gt;
		  &lt;/tr&gt;&lt;tr data-v-order-totals-total&gt;
			&lt;td colspan=&quot;4&quot;&gt;
			  &lt;small data-v-order-total-title&gt;-10% Discount&lt;/small&gt;:
			&lt;/td&gt;
			&lt;td data-v-order-total-value_formatted&gt;$-384.20&lt;/td&gt;
		  &lt;/tr&gt;&lt;tr data-v-order-totals-total&gt;
			&lt;td colspan=&quot;4&quot;&gt;
			  &lt;small data-v-order-total-title&gt;Fast courier&lt;/small&gt;:
			&lt;/td&gt;
			&lt;td data-v-order-total-value_formatted&gt;$0.00&lt;/td&gt;
		  &lt;/tr&gt;&lt;tr data-v-order-totals-total&gt;
			&lt;td colspan=&quot;4&quot;&gt;
			  &lt;small data-v-order-total-title&gt;VAT (9%)&lt;/small&gt;:
			&lt;/td&gt;
			&lt;td data-v-order-total-value_formatted&gt;$270.00&lt;/td&gt;
		  &lt;/tr&gt;&lt;tr data-v-order-totals-total&gt;
			&lt;td colspan=&quot;4&quot;&gt;
			  &lt;small data-v-order-total-title&gt;Green tax (1.00)&lt;/small&gt;:
			&lt;/td&gt;
			&lt;td data-v-order-total-value_formatted&gt;$2.00&lt;/td&gt;
		  &lt;/tr&gt;&lt;tr data-v-order-totals-total&gt;
			&lt;td colspan=&quot;4&quot;&gt;
			  &lt;small data-v-order-total-title&gt;VAT (19%)&lt;/small&gt;:
			&lt;/td&gt;
			&lt;td data-v-order-total-value_formatted&gt;$570.00&lt;/td&gt;
		  &lt;/tr&gt;                  
		  
		  
		  &lt;tr&gt;
			&lt;td colspan=&quot;4&quot;&gt;Total:&lt;/td&gt;
			&lt;td data-v-order-total_formatted&gt;$3,457.80&lt;/td&gt;
		  &lt;/tr&gt;
		&lt;/tfoot&gt;

	  &lt;/table&gt;

	


	&lt;div data-v-order&gt;

	  &lt;div&gt;
		  &lt;span data-v-order-order_status&gt;pending&lt;/span&gt;
	  &lt;/div&gt;
	  
	  &lt;div&gt;
		&lt;div class=&quot;row&quot;&gt;
		  &lt;div class=&quot;col-6&quot;&gt;

			  &lt;div&gt;
				&lt;div&gt;
				  &lt;h6&gt;Customer Details&lt;/h6&gt;
				&lt;/div&gt;
				&lt;div&gt;
				  &lt;div data-v-order-first_name data-first_name-text&gt;John&lt;/div&gt;
				  &lt;div data-v-order-last_name data-last_name-text&gt;Doe&lt;/div&gt;
				  &lt;div data-v-order-email data-email-text&gt;johndoe@example.com&lt;/div&gt;
				  &lt;div data-v-order-phone_number data-phone_number-text&gt;12345678&lt;/div&gt;
				&lt;/div&gt;
			  &lt;/div&gt;
			  
		  &lt;/div&gt;
		  &lt;div class=&quot;col-6&quot;&gt;
			  &lt;div&gt;
				&lt;div&gt;
				  &lt;h6&gt;Order Details&lt;/h6&gt;
				&lt;/div&gt;

				&lt;div&gt;
					&lt;table&gt;
					&lt;tbody&gt;&lt;tr&gt;
					  &lt;td&gt;
						&lt;span&gt;Order ID:&lt;/span&gt;
					  &lt;/td&gt;
					  &lt;td&gt;
						&lt;span data-v-order-order_id&gt;6&lt;/span&gt;
					  &lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
					  &lt;td&gt;
						&lt;span&gt;Order Date:&lt;/span&gt;
					  &lt;/td&gt;
					  &lt;td&gt;
						&lt;details&gt;
						  &lt;summary&gt;
							&lt;span&gt;
							  &lt;span data-v-order-created_at data-filter-friendly_date&gt;1 hour from now&lt;/span&gt;
						  &lt;/span&gt;&lt;/summary&gt;
						  &lt;p&gt;
							&lt;span data-v-order-created_at&gt;2026-03-26 16:00:25&lt;/span&gt;
							
						  &lt;/p&gt;
						&lt;/details&gt;
					  &lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;
					  &lt;td&gt;
						&lt;span&gt;Payment method:&lt;/span&gt;
					  &lt;/td&gt;
					  &lt;td&gt;
						&lt;details&gt;
						  &lt;summary&gt;
							&lt;span&gt;
							  &lt;span data-v-order-payment_title&gt;Cash on delivery&lt;/span&gt;
						  &lt;/span&gt;&lt;/summary&gt;
						  &lt;p&gt;
							&lt;span data-v-order-payment_method&gt;cash-on-delivery&lt;/span&gt;
							
							&lt;br&gt;
							&lt;span data-v-order-payment_description&gt;Cash on delivery&lt;/span&gt;
							&lt;br&gt;
						  &lt;/p&gt;
						&lt;/details&gt;
					  &lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;
					  &lt;td&gt;
						&lt;span&gt;Shipping method:&lt;/span&gt;
					  &lt;/td&gt;
					  &lt;td&gt;
						&lt;details&gt;
						  &lt;summary&gt;
							&lt;span data-v-order-shipping_title&gt;Fast courier&lt;/span&gt;
						  &lt;/summary&gt;

						  &lt;p&gt;
							&lt;span data-v-order-shipping_method&gt;fast-courier&lt;/span&gt;
							
							&lt;br&gt;
							&lt;span data-v-order-shipping_description&gt;Fast courier&lt;/span&gt;
							&lt;br&gt;
						  &lt;/p&gt;
						&lt;/details&gt;
					  &lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;
					  &lt;td&gt;
						&lt;span&gt;Order Total:&lt;/span&gt;
					  &lt;/td&gt;
					  &lt;td&gt;
						&lt;span data-v-order-total_formatted&gt;$3,457.80&lt;/span&gt;
					  &lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;
					  &lt;td&gt;
						&lt;span&gt;Reward points:&lt;/span&gt;
					  &lt;/td&gt;
					  &lt;td&gt;
						&lt;span data-v-order-points&gt;&lt;/span&gt;
					  &lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;&lt;td&gt;
					  &lt;span&gt;Status&lt;/span&gt;
					&lt;/td&gt;
					&lt;td&gt;
					  &lt;span data-v-order-order_status&gt;pending&lt;/span&gt;
					  
					&lt;/td&gt;
					
				  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				  
				&lt;/div&gt;

			  &lt;/div&gt;
		  &lt;/div&gt;
		  &lt;div class=&quot;col-6&quot;&gt;

			  &lt;div&gt;
				&lt;h6&gt;Billing Address&lt;/h6&gt;
				&lt;div&gt;
				  &lt;div data-v-order-billing_first_name data-billing_first_name-text&gt;John&lt;/div&gt;
				  &lt;div data-v-order-billing_last_name data-billing_last_name-text&gt;Doe&lt;/div&gt;
				  &lt;div data-v-order-billing_company data-billing_company-text&gt;&lt;/div&gt;
				  &lt;div data-v-order-billing_address_1 data-billing_address_1-text&gt;test test&lt;/div&gt;
				  &lt;div data-v-order-billing_address_2 data-billing_address_2-text&gt;test&lt;/div&gt;
				  &lt;div data-v-order-billing_city data-billing_city-text&gt;asdsad&lt;/div&gt;
				  &lt;div data-v-order-billing_post_code data-billing_post_code-text&gt;1223&lt;/div&gt;
				  &lt;div data-v-order-billing_country data-billing_country_id&gt;United States&lt;/div&gt;
				  &lt;div data-v-order-billing_region data-billing_region&gt;Alaska&lt;/div&gt;

			  &lt;/div&gt;

			&lt;/div&gt;
		  &lt;/div&gt;
		  &lt;div class=&quot;col-6&quot;&gt;

			  &lt;div&gt;
				&lt;h6&gt;Shipping Address&lt;/h6&gt;
				&lt;div&gt;
				  &lt;div data-v-order-shipping_first_name data-shipping_first_name-text&gt;John&lt;/div&gt;
				  &lt;div data-v-order-shipping_last_name data-shipping_last_name-text&gt;Doe&lt;/div&gt;
				  &lt;div data-v-order-shipping_company data-shipping_company-text&gt;&lt;/div&gt;
				  &lt;div data-v-order-shipping_address_1 data-shipping_address_1-text&gt;test test&lt;/div&gt;
				  &lt;div data-v-order-shipping_address_2 data-shipping_address_2-text&gt;test&lt;/div&gt;
				  &lt;div data-v-order-shipping_city data-shipping_city-text&gt;asdsad&lt;/div&gt;
				  &lt;div data-v-order-shipping_post_code data-shipping_post_code-text&gt;1223&lt;/div&gt;
				  &lt;div data-v-order-shipping_country data-shipping_country_id-text&gt;United States&lt;/div&gt;
				  &lt;div data-v-order-shipping_region data-shipping_region_id-text&gt;Alaska&lt;/div&gt;

			  &lt;/div&gt;

			&lt;/div&gt;
		  &lt;/div&gt;
		&lt;/div&gt;
	  &lt;/div&gt;

	&lt;/div&gt;


  &lt;/div&gt;
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="139">
			<title data-v-post-name="name">Components</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/Components</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Overview 
Component object is used to define the html blocks that can be added and edited on the page. 
To add a component you need to use Vvveb.Components.add method or extend an existing component, ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<h2>Overview</h2>
<p>Component object is used to define the html blocks that can be added and edited on the page.</p>
<p>To add a component you need to use <code>Vvveb.Components.add</code> method or extend an existing component, like a base component with <code>Vvveb.Components.extend</code></p>
<p>For example image component extends _base component and is defined as</p>
<pre><code class="language-js">Vvveb.Components.extend(&quot;_base&quot;, &quot;html/image&quot;, {
    nodes: [&quot;img&quot;],
    name: &quot;Image&quot;,
    html: '&lt;img src=&quot;../libs/builder/icons/image.svg&quot; height=&quot;128&quot; width=&quot;128&quot;&gt;',
    image: &quot;icons/image.svg&quot;,
    properties: [{
        name: &quot;Image&quot;,
        key: &quot;src&quot;,
        htmlAttr: &quot;src&quot;,
        inputtype: FileUploadInput
    }, {
        name: &quot;Width&quot;,
        key: &quot;width&quot;,
        htmlAttr: &quot;width&quot;,
        inputtype: TextInput
    }, {
        name: &quot;Height&quot;,
        key: &quot;height&quot;,
        htmlAttr: &quot;height&quot;,
        inputtype: TextInput
    }, {
        name: &quot;Alt&quot;,
        key: &quot;alt&quot;,
        htmlAttr: &quot;alt&quot;,
        inputtype: TextInput
    }]
});
</code></pre>
<p>Base component does not extend any existing component and is using  <code>Vvveb.Components.add</code> being defined as</p>
<pre><code class="language-js">Vvveb.Components.add(&quot;_base&quot;, {
    name: &quot;Element&quot;,
	properties: [{
        name: &quot;Id&quot;,
        key: &quot;id&quot;,
        htmlAttr: &quot;id&quot;,
        inputtype: TextInput
    }, {
        name: &quot;Class&quot;,
        key: &quot;class&quot;,
        htmlAttr: &quot;class&quot;,
        inputtype: TextInput
    }]
});
</code></pre>
<p>In this way any component that extends <em>_base</em> component inherits two properties id and class used to edit the corresponding html attributes.</p>
<p><em>Note</em>: _base component is loaded for any html node that has no specific component assigned, for example when clicking on a regular <em>span</em> node.</p>
<h2>Component definition</h2>
<p>Component object can have the following keys</p>
<ul>
<li><strong>name</strong> - Used to display the name on the components list in the left panel.</li>
<li><strong>image</strong> - Image url to display in the components list.</li>
<li><strong>html</strong> - When dropping the component on the page this html is used to insert it in the page.</li>
<li><strong>nodes</strong> - An array with dom node names to allow the editor to detect the Component when clicking on the corresponding node, example <code>nodes: [&quot;h1&quot;, &quot;h2&quot;,&quot;h3&quot;, &quot;h4&quot;,&quot;h5&quot;,&quot;h6&quot;],</code> or <code>nodes: [&quot;img&quot;],</code></li>
<li><strong>classes</strong> - An array with class names to allow the editor to detect the Component when clicking on the corresponding node, example <code>classes: [&quot;btn&quot;, &quot;btn-link&quot;]</code></li>
<li><strong>classesRegex</strong> - An array with regexs used for class names to allow the editor to detect the Component when clicking on the corresponding node, example <code>classesRegex: [&quot;col-&quot;],</code> this regex is used by Grid Component to detect bootstrap columns such as col-md-3 or col-sm-6.</li>
<li><strong>attributes</strong> - An array with attributes  names to allow the editor to detect the Component when clicking on the corresponding node, example <code>attributes: [&quot;data-component-maps&quot;],</code> this attribute is used by maps component.</li>
<li><strong>afterDrop</strong> -  <em>function (node) {}</em>  A function that is called after the element is droped, the node of the new element is passed as parameter, for example map component uses this function to change the html of the node fom a image of a map with the actual map iframe for performance reasons when dragging.</li>
<li><strong>init</strong> - <em>function (node) {}</em> A function that is called after the Component properties are loaded and displayed in the right panel , the node of the new element is passed as parameter, for example video component that supports youtube, vimeo and html5 uses this event to hide vimeo and html5 inputs when a youtube video is detected.</li>
<li><strong>beforeInit</strong> - <em>function (node) {}</em> A function that is called before Component properties are displayed , the node of the new element is passed as parameter, this can be useful to dinamically change component properties for example Select Input or Grid component that needs to load a variable number of inputs based on child nodes uses this event to alter component properties and add the necessary properties for each child node.</li>
<li><strong>onChange</strong> - <em>function (node, property, value)</em> This event is called when a component input in the right panel is changed, the first parameter is the dom <em>node</em> that is edited, second parameter <em>property</em> is the name of the property that has changed (the <em>key</em> attribute of the property), <em>value</em> is the new value of the property.
Usually each input has it's own onChange event but because the component onChange event is triggered for all inputs can be usefull when using a common function to process all input changes.
This event is usefull when changing complex features, for example the map component uses it to compose a new google maps url by adding all component properties such as latitude, longitude and zoom etc.</li>
<li><strong>properties</strong> - A collection of inputs and corespponding configuration for each, to allow the Component to be edited.</li>
</ul>
<p>A complete Component definition with all possible keys</p>
<pre><code class="language-js">Vvveb.Components.extend(&quot;_base&quot;, &quot;html/image&quot;, {
	name: &quot;Image&quot;,
	image: &quot;icons/image.svg&quot;,
	html: '&lt;img src=&quot;../libs/builder/icons/image.svg&quot; height=&quot;128&quot; width=&quot;128&quot;&gt;',
	nodes: [&quot;img&quot;],
	classes: [&quot;btn&quot;, &quot;btn-link&quot;],
	attributes: [&quot;data-component-maps&quot;],
	afterDrop: function (node) {},
	init: function (node) {},
	beforeInit: function (node) {},
	onChange: function (node, property, value) {},
	properties: [{
		name: &quot;Id&quot;,
		key: &quot;id&quot;,
		htmlAttr: &quot;id&quot;,
		inputtype: TextInput
    }
});   
</code></pre>
<h2>Component properties</h2>
<p>Component properties are used to define the inputs that are used to edit the component.</p>
<pre><code class="language-js">properties: [{
        name: &quot;Id&quot;,
        key: &quot;id&quot;,
        htmlAttr: &quot;id&quot;,
        inputtype: TextInput
    }, {
        name: &quot;Class&quot;,
        key: &quot;class&quot;,
        htmlAttr: &quot;class&quot;,
        inputtype: TextInput
    }]
</code></pre>
<p>A property can have the following keys</p>
<ul>
<li><strong>name</strong> - Used as label for the input.</li>
<li><strong>key</strong> - Unique identifier for the input, this is pased on component <em>onChange</em> event second parameter <em>property</em>.</li>
<li><strong>inputtype</strong> - The input type used for the property, any Input object such as TextInput, SelectInput, ToggleInput, ColorInput etc from <em>inputs.js</em> can be used.</li>
<li><strong>htmlAttr</strong> - If htmlAttr is specified then the value is used to edit the coresponding html attribute, the input is filled automatically with the initial value of the attribute and updated automatically when the input is changed, no need to use onChange event, for example <em>htmlAttr: &quot;id&quot;,</em>
<ul>
<li><strong>style</strong> - If htmlAttr is set to <em>style</em> then the property key is used as the css property to be edited, in the example below <em>background-color</em> css property is edited directly using ColorInput that will display a color picker.</li>
<li><strong>class</strong> - If htmlAttr is set to <em>class</em> and the property has <em>validValues</em> key then all classed that are contained in validValues array are removed before adding the new value, this can be usefull when having a select input to choose a unique class from a set.
For example in the example below bootstrap container component uses validValues to allow either <em>container</em> or <em>container-fluid</em> class to be added from a select.</li>
</ul>
</li>
</ul>
<pre><code class="language-js">properties: [
{
	name: &quot;Background Color&quot;,
	key: &quot;background-color&quot;,
	htmlAttr: &quot;style&quot;,
	inputtype: ColorInput,
},
{
	name: &quot;Type&quot;,
	key: &quot;type&quot;,
	htmlAttr: &quot;class&quot;,
	inputtype: SelectInput,
	validValues: [&quot;container&quot;, &quot;container-fluid&quot;],
	data: {
		options: [{
			value: &quot;container&quot;,
			text: &quot;Default&quot;
		}, {
			value: &quot;container-fluid&quot;,
			text: &quot;Fluid&quot;
		}]
	}        name: &quot;Class&quot;,
	key: &quot;class&quot;,
	htmlAttr: &quot;class&quot;,
	inputtype: TextInput
}]
</code></pre>
<ul>
<li><strong>onChange</strong> - <em>function(node, value)</em> This event is triggered when the input is changed (this can depend on Input definition, check inputs.js) you can use this when htmlAttr or style is not enough.</li>
<li><strong>init</strong> - <em>function(node)</em> This function is called when the input is initialized, this can be used for example to load the input with a different value than default.
For example when editing width css property and using a NumberInput you need to use init to remove the px from &quot;100px&quot; to set the value for NumberInput correctly.</li>
</ul>
<pre><code class="language-js">{
	name: &quot;Width&quot;,
	key: &quot;width&quot;,
	htmlAttr: &quot;style&quot;,
	parent:&quot;&quot;,
	inputtype: NumberInput,//can also be replaced with RangeInput
	data: {
		value: &quot;320&quot;,//default
		min: &quot;50&quot;,
		max: &quot;1024&quot;,
		step: &quot;10&quot;
	},
	init: function (node)//use init because number input does not ignore &quot;px&quot;
	{
		return parseInt($(node).css(&quot;width&quot;));//remove px
	}
}
</code></pre>
<ul>
<li><strong>data</strong> - Some Inputs need aditional data, for example ToggleInput needs values for <em>on</em> and <em>off</em> states, or SelectInput needs <em>data:{options: [{}]}</em> for values
For example using toggle to set disabled to true or false for a bootstrap button</li>
</ul>
<pre><code class="language-js">//ToggleInput
{
	name: &quot;Disabled&quot;,
	key: &quot;disabled&quot;,
	htmlAttr: &quot;disabled&quot;,
	inputtype: ToggleInput,
	data: {
		on: &quot;disabled-true&quot;,
		off: &quot;disabled-false&quot;
	}
}
//SelectInput
{
        name: &quot;Size&quot;,
        key: &quot;size&quot;,
        htmlAttr: &quot;class&quot;,
        inputtype: SelectInput,
        validValues: [&quot;btn-lg&quot;, &quot;btn-sm&quot;],
        data: {
            options: [{
                value: &quot;&quot;,
                text: &quot;Default&quot;
            }, {
                value: &quot;btn-lg&quot;,
                text: &quot;Large&quot;
            }, {
                value: &quot;btn-sm&quot;,
                text: &quot;Small&quot;
            }]
        }
    }
</code></pre>
<ul>
<li><strong>child</strong> - Sometimes you need to edit a node that is inside the parent node, for this you can use <em>child</em> property the value must be the css selector for the child element.
For example bootstrap progress bar component has two divs, one for background and one for the progress to use a input to change the progress div instead of the background div, child is set as <em>child:&quot;.progress-bar&quot;</em>.</li>
</ul>
<pre><code class="language-js">{
	name: &quot;Animated&quot;,
	key: &quot;animated&quot;,
	child:&quot;.progress-bar&quot;,
	htmlAttr: &quot;class&quot;,
	validValues: [&quot;&quot;, &quot;progress-bar-animated&quot;],
	inputtype: ToggleInput,
	data: {
		on: &quot;progress-bar-animated&quot;,
		off: &quot;&quot;,
	}
}	
</code></pre>
<ul>
<li><strong>parent</strong> - Same as child but used to edit parent elements, when only parent is set with no selector then the parentNode is used, if a css selector is used then the selector is used to find parent node (this uses jQuery.parents())</li>
</ul>
<h2>Component group</h2>
<p>For a component to be visible in the left panel and to be used for drag and drop it needs to be added to a component group, you can do this by including it in the <code>Vvveb.ComponentsGroup</code> array using the group name as a key.</p>
<p>For example Widgets component group has the following definition.</p>
<pre><code class="language-js">Vvveb.ComponentsGroup['Widgets'] = [&quot;widgets/googlemaps&quot;, &quot;widgets/video&quot;];
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="140">
			<title data-v-post-name="name">Inputs</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/Inputs</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Overview 
Inputs objects are used to edit component properties 
For example TextInput extends Input object and is defined as 
var TextInput = $.extend({}, Input, { events: { &quot;keyup&quot;: ['onCha]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<h2>Overview</h2>
<p>Inputs objects are used to edit component properties</p>
<p>For example TextInput extends Input object and is defined as</p>
<pre><code class="language-js">var TextInput = $.extend({}, Input, {

    events: {
        &quot;keyup&quot;: ['onChange', 'input'],
	 },

	setValue: function(value) {
		$('input', this.element).val(value);
	},
	
	init: function(data) {
		return this.render(&quot;textinput&quot;, data);
	},
  }
);
</code></pre>
<p>Inputs also require a template that is defined as a <script> tag in the editor html (inside editor.html) with the id <code>vvveb-input-inputname</code> for example for text input is <code>vvveb-input-textinput</code> and is defined as</p>
<pre><code class="language-js">&lt;script id=&quot;vvveb-input-textinput&quot; type=&quot;text/html&quot;&gt;
	
	&lt;div&gt;
		&lt;input name=&quot;{%=key%}&quot; type=&quot;text&quot; class=&quot;form-control&quot;/&gt;
	&lt;/div&gt;
	
&lt;/script&gt;
</code></pre>
<p>{%=key%} is used to set the unique input name defined as &quot;key&quot; in component properties, if additional data is provided then these must be set in the template, for example ToggleInput needs <em>on</em> and <em>off</em></p>
<pre><code class="language-js">&lt;script id=&quot;vvveb-input-toggle&quot; type=&quot;text/html&quot;&gt;
	
    &lt;div class=&quot;toggle&quot;&gt;
        &lt;input type=&quot;checkbox&quot; name=&quot;{%=key%}&quot; value=&quot;{%=on%}&quot; data-value-off=&quot;{%=off%}&quot; data-value-on=&quot;{%=on%}&quot; class=&quot;toggle-checkbox&quot; id=&quot;{%=key%}&quot;&gt;
...
</code></pre>
<h2>Definition</h2>
<p>Usually Input objects define the following keys</p>
<ul>
<li><em>events</em> - This provides a collection of definitions for functions to be called on certain events, the format is <em>event_name :['InputObject_function_to_be_called', 'css_selector_for_element_in_template']</em>
For example text input monitors keyup event for input element in the template, while select input monitors onchange event for select element in template, by default they both call onChange function on parent Input object.</li>
</ul>
<pre><code class="language-js">var TextInput = $.extend({}, Input, {

    events: {
        &quot;keyup&quot;: ['onChange', 'input'],
	 },
...


var SelectInput = $.extend({}, Input, {
	

    events: {
        &quot;change&quot;: ['onChange', 'select'],
	 },
...
</code></pre>
<p>Sometimes you need to read another attribute than value from the input such as checked for checkbox in this case you need to override onChange method to use <em>checked</em> attribute.</p>
<pre><code class="language-js">var CheckboxInput = $.extend({}, Input, {

	onChange: function(event, node) {
		
		if (event.data &amp;&amp; event.data.element)
		{
			event.data.element.trigger('propertyChange', [this.checked, this]);
		}
	},
</code></pre>
<ul>
<li><em>setValue</em> - This method is called automatically by Vvveb.Builder when setting the value for the input.</li>
<li><em>init</em> - This method is called when the input is initialized, the return value is used as html to render the input, by default the parent Input.render() is called with the template name and additional data as parameters.</li>
</ul>
<h2>Parent Input</h2>
<p>All input object extends Input object that handles template loading and processing and also provides a default onChange function that automatically processes events using value attribute.</p>
<pre><code class="language-js">var Input = {
	
	init: function(name) {
	},


	onChange: function(event, node) {
		
		if (event.data &amp;&amp; event.data.element)
		{
			event.data.element.trigger('propertyChange', [this.value, this]);
		}
	},

	renderTemplate: function(name, data) {
		return tmpl(&quot;vvveb-input-&quot; + name, data);
	},

	render: function(name, data) {
		this.element = $(this.renderTemplate(name, data));
		
		//bind events
		if (this.events)
		for (var event in this.events)
		{
			fun = this[ this.events[event][0] ];
			el = this.events[event][1];
		
			this.element.on(event, el, {element: this.element}, fun);
		}
		
		return this.element;
	}
};
</code></pre>
<p>You can check editor.html for input templates and inputs.js for inputs code.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="141">
			<title data-v-post-name="name">VvvebJs page builder</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/vvvebjs-page-builder</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[VvvebJs is the page builder at the heart of Vvveb CMS. 
The major difference from other page builders is that VvvebJs can edit any element and place elements anywhere on the page or inside any other e]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>VvvebJs is the page builder at the heart of Vvveb CMS.</p>
<p>The major difference from other page builders is that VvvebJs can edit any element and place elements anywhere on the page or inside any other element without any limitation.
It also allows live editing of the html code of the page without restrictions.</p>
<p>VvvebJs is also a real WYSIWYG editor meaning that there is no difference between the edited page and the final result.</p>
<p>Because Vvveb CMS uses plain html templates for themes this allows the user through VvvebJs unlimited flexibility in customizing the site with an easy to use no code experience.</p>
<p>Every page of the CMS from user registration page or checkout page to email templates can be edited from VvvebJs.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="142">
			<title data-v-post-name="name">Home</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/Home</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Overview 
The editor is build using Bootstrap 4 and jQuery. 
The editor html is located in editor.html and to load the demo editor the following scripts are included. 
&lt;!-- jquery--&gt; &lt;script ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<h2>Overview</h2>
<p>The editor is build using Bootstrap 4 and jQuery.</p>
<p>The editor html is located in editor.html and to load the demo editor the following scripts are included.</p>
<pre><code class="language-html">&lt;!-- jquery--&gt;
&lt;script src=&quot;js/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;!-- Enable shortcut support such as ctrl+z for undo and ctrl+e for export etc--&gt;
&lt;script src=&quot;js/jquery.hotkeys.js&quot;&gt;&lt;/script&gt;


&lt;!-- bootstrap--&gt;
&lt;script src=&quot;js/popper.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/bootstrap.min.js&quot;&gt;&lt;/script&gt;

&lt;!-- builder code--&gt;
&lt;!-- This is the main editor code --&gt;
&lt;script src=&quot;libs/builder/builder.js&quot;&gt;&lt;/script&gt;

&lt;!-- undo manager--&gt;
&lt;script src=&quot;libs/builder/undo.js&quot;&gt;&lt;/script&gt;

&lt;!-- inputs--&gt;
&lt;!-- The inputs library, here is the code for inputs such as text, select etc used for component properties --&gt;
&lt;script src=&quot;libs/builder/inputs.js&quot;&gt;&lt;/script&gt;

&lt;!-- components--&gt;
&lt;!-- Components for Bootstrap 4 group --&gt;
&lt;script src=&quot;libs/builder/components-bootstrap4.js&quot;&gt;&lt;/script&gt;
&lt;!-- Components for Widgets group --&gt;
&lt;script src=&quot;libs/builder/components-widgets.js&quot;&gt;&lt;/script&gt;


&lt;!-- plugins --&gt;

&lt;!-- code mirror libraries - code editor syntax highlighting for html editor --&gt;
&lt;link href=&quot;libs/codemirror/lib/codemirror.css&quot; rel=&quot;stylesheet&quot;/&gt;
&lt;link href=&quot;libs/codemirror/theme/material.css&quot; rel=&quot;stylesheet&quot;/&gt;
&lt;script src=&quot;libs/codemirror/lib/codemirror.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;libs/codemirror/lib/xml.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;libs/codemirror/lib/formatting.js&quot;&gt;&lt;/script&gt;

&lt;!-- code mirror vvveb plugin --&gt;
&lt;!-- replaces default textarea as html code editor with codemirror--&gt;
&lt;script src=&quot;libs/builder/plugin-codemirror.js&quot;&gt;&lt;/script&gt;	

</code></pre>
<p>To initialize the editor Vvveb.Builder.init is called.</p>
<p>The first parameter is the url to load for editing, this must be on the same subdomain to allow editing.</p>
<p>The second parameter is a function to call when the page is finished loading, by default the editor Gui.init() is called.</p>
<pre><code class="language-javascript">$(document).ready(function() 
{
	Vvveb.Builder.init('demo/index.html', function() {
		//load code after page is loaded here
		Vvveb.Gui.init();
	});
});
&lt;/script&gt;
</code></pre>
<h2>Structure</h2>
<p>[[img/structure.png]]</p>
<p><code>Component Group</code> is a collection of <a href="Components">Components</a>, for example Bootstrap 4 group is composed of Components such as <code>Button</code> and <code>Grid</code>, this object is used only for grouping components in the editor left panel.</p>
<p>For example Widgets component group has only two components video and maps and is defined as</p>
<pre><code class="language-javascript">Vvveb.ComponentsGroup['Widgets'] = [&quot;widgets/googlemaps&quot;, &quot;widgets/video&quot;];
</code></pre>
<p>A <a href="Components">Component</a> is an object that provides html that can be dropped on the canvas and also properties that can be edited when the component is selected, for example Video Component.</p>
<p>The html link <a href="Components">Component</a> that has Url and Target properties is defined as</p>
<pre><code class="language-javascript">Vvveb.Components.extend(&quot;_base&quot;, &quot;html/link&quot;, {
    nodes: [&quot;a&quot;],
    name: &quot;Link&quot;,
    properties: [{
        name: &quot;Url&quot;,
        key: &quot;href&quot;,
        htmlAttr: &quot;href&quot;,
        inputtype: LinkInput
    }, {
        name: &quot;Target&quot;,
        key: &quot;target&quot;,
        htmlAttr: &quot;target&quot;,
        inputtype: TextInput
    }]
});
</code></pre>
<p>An <a href="Inputs">Input</a> object is used in <a href="Components">Component</a> properties collection for editing the property, for example text input, select, color, grid row etc
For example TextInput extends Input object and is defined as</p>
<pre><code class="language-js">var TextInput = $.extend({}, Input, {

    events: {
        &quot;keyup&quot;: ['onChange', 'input'],
	 },

	setValue: function(value) {
		$('input', this.element).val(value);
	},
	
	init: function(data) {
		return this.render(&quot;textinput&quot;, data);
	},
  }
);
</code></pre>
<p>Inputs also require a template that is defined as a <script> tag in the editor html (inside editor.html) with the id <code>vvveb-input-inputname</code> for example for text input is <code>vvveb-input-textinput</code> and is defined as</p>
<pre><code class="language-js">&lt;script id=&quot;vvveb-input-textinput&quot; type=&quot;text/html&quot;&gt;
	
	&lt;div&gt;
		&lt;input name=&quot;{%=key%}&quot; type=&quot;text&quot; class=&quot;form-control&quot;/&gt;
	&lt;/div&gt;
	
&lt;/script&gt;
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="143">
			<title data-v-post-name="name">Events list</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/events-list</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Vvveb CMS exposes a wide set of events that allow plugins and extensions to modify data, inject functionality, or react to system actions. 
Events are triggered throughout components, controllers, and]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Vvveb CMS exposes a wide set of events that allow plugins and extensions to modify data, inject functionality, or react to system actions.</p>
<p>Events are triggered throughout components, controllers, and core systems, giving developers flexible integration points without modifying core code.</p>
<hr />
<h2>Component Events</h2>
<p>Every component triggers at least one event in its <code>results()</code> method. This allows plugins to filter or modify the data returned by the component before it is rendered.</p>
<pre><code class="language-php">list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
</code></pre>
<p>You can attach to any component’s <code>results</code> event:</p>
<pre><code class="language-php">// filter comments and add gravatars for users that don't have an avatar,  __CLASS__ is usually used instead of 'Vvveb\Plugins\GravatarPlugin' for convenience.
Event::on('Vvveb\Component\Comments', 'results', 'Vvveb\Plugins\GravatarPlugin' , function ($comments) {
	foreach ($comments['comments'] as &amp;$comment) {
		$comment['avatar'] = 'https://www.gravatar.com/avatar/' . md5(strtolower($comment['email']));
	}
	return [$comments];
});
</code></pre>
<p>This pattern applies to all components.<br />
View <a href="/cat/components">components list</a></p>
<hr />
<h2>Admin Events</h2>
<h3>Admin Menu</h3>
<p>Plugins can add items to the admin dashboard menu by attaching to the <code>init-menu</code> event in the <code>Vvveb\Controller\Base</code> namespace.</p>
<pre><code class="language-php">// add a new entry in the admin dashboard menu, used by plugins to add a link to plugin settings
Event::on('Vvveb\Controller\Base', 'init-menu', __CLASS__, function ($menu) use ($admin_path) {
	$menu['plugins']['items']['insert-scripts'] = [
		'name'     =&gt; __('Insert scripts'),
		'url'      =&gt; $admin_path . '?module=plugins/insert-scripts/settings',
		//'icon-img' =&gt; PUBLIC_PATH . 'plugins/insert-scripts/insert-scripts.svg',
		'icon'      =&gt; 'icon-storefront-outline',
	];

	return [$menu];
});
</code></pre>
<p>This is the primary hook for extending the admin interface.</p>
<hr />
<h2>Core System Events</h2>
<h3>View Rendering</h3>
<p><code>Vvveb\System\Core\View</code></p>
<ul>
<li>
<p><strong>compile</strong> - Parameters: <code>$template</code>, <code>$tplFile</code>, <code>$templateEngine</code>, <code>$view</code><br />
Triggered when a template is compiled. Useful for inserting additional template files or modifying template behavior.</p>
</li>
<li>
<p><strong>render</strong> - Parameters: <code>$template</code>, <code>$filename</code>, <code>$tplFile</code>, <code>$templateEngine</code>, <code>$view</code><br />
Triggered before rendering. Useful for adding data to the view or altering output.</p>
</li>
</ul>
<h3>Image Processing</h3>
<p><code>Vvveb\System\Images</code></p>
<ul>
<li>
<p><strong>publicPath</strong> - Parameters: <code>$publicPath</code>, <code>$type</code>, <code>$image</code>, <code>$size</code><br />
Modify the public path or metadata before an image is resized.</p>
</li>
<li>
<p><strong>image</strong> - Parameters: <code>$image</code>, <code>$type</code>, <code>$size</code><br />
Modify the final image path or metadata after resizing.</p>
</li>
</ul>
<hr />
<h2>Extension Events</h2>
<h3>Extensions Manager</h3>
<p><code>Vvveb\System\Extensions\Extensions</code></p>
<ul>
<li><strong>install</strong> - Parameters: <code>$extensionZipFile</code>, <code>$success</code><br />
Triggered when a plugin or theme is installed.</li>
</ul>
<h3>Themes</h3>
<p><code>Vvveb\System\Extensions\Themes</code></p>
<ul>
<li><strong>install</strong> - Parameters: <code>$extensionZipFile</code>, <code>$success</code><br />
Triggered when a theme is installed.</li>
</ul>
<h3>Plugins</h3>
<p><code>Vvveb\System\Extensions\Plugins</code></p>
<ul>
<li>
<p><strong>setup</strong> - Parameters: <code>$pluginName</code>, <code>$site_id</code><br />
Triggered on first activation. Ideal for creating tables or initial setup.</p>
</li>
<li>
<p><strong>activate</strong> - Parameters: <code>$pluginName</code>, <code>$site_id</code><br />
Triggered when a plugin is activated.</p>
</li>
<li>
<p><strong>deactivate</strong> - Parameters: <code>$pluginName</code>, <code>$site_id</code><br />
Triggered when a plugin is deactivated.</p>
</li>
<li>
<p><strong>uninstall</strong> - Parameters: <code>$pluginName</code>, <code>$success</code><br />
Triggered when a plugin is removed.</p>
</li>
</ul>
<hr />
<h2>Controller Events</h2>
<h3>Feed Controller</h3>
<p><code>Vvveb\Controller\Feed</code></p>
<ul>
<li><strong>index</strong> - Parameters: <code>$results</code><br />
Triggered after feed data is processed.</li>
</ul>
<h3>Post Controller</h3>
<p><code>Vvveb\Controller\Post</code></p>
<ul>
<li><strong>index</strong> - Parameters: <code>$content</code>, <code>$language</code>, <code>$slug</code><br />
Triggered before post data is processed on the post page.</li>
</ul>
<h3>Product Controller</h3>
<p><code>Vvveb\Controller\Product</code></p>
<ul>
<li><strong>index</strong> - Parameters: <code>$content</code>, <code>$language</code>, <code>$slug</code><br />
Triggered before product data is processed on the product page.</li>
</ul>
<h3>User Login</h3>
<p><code>Vvveb\Controller\User\Login</code></p>
<ul>
<li><strong>login</strong> - Parameters: <code>$userInfo</code><br />
Triggered before login validation. Returning <code>false</code> cancels login.</li>
</ul>
<h3>User Signup</h3>
<p><code>Vvveb\Controller\User\Signup</code></p>
<ul>
<li><strong>addUser</strong> - Parameters: <code>$userInfo</code><br />
Triggered before user creation. Returning <code>false</code> cancels signup.</li>
</ul>
<h3>User Password Reset</h3>
<p><code>Vvveb\Controller\User\Reset</code></p>
<ul>
<li><strong>index</strong> - Parameters: <code>$loginData</code><br />
Triggered before password reset validation. Returning <code>false</code> cancels the reset request.</li>
</ul>
<hr />
<p>These events form the backbone of Vvveb’s extensibility.
They allow plugins to integrate deeply into the system while keeping core code untouched.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="144">
			<title data-v-post-name="name">Events introduction</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/events-introduction</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Events in Vvveb CMS provide extension points where data can be modified or additional actions can be performed. 
They are the primary mechanism that plugins use to extend or customize Vvveb’s behavi]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Events in Vvveb CMS provide extension points where data can be modified or additional actions can be performed.</p>
<p>They are the primary mechanism that plugins use to extend or customize Vvveb’s behavior without altering core code.</p>
<p>All event handling is managed through the <code>Vvveb\System\Event</code> class.</p>
<hr />
<h2>Registering Events</h2>
<p>To run custom code when an event occurs, use the <code>Event::on()</code> method:</p>
<pre><code class="language-php">function on($namespace, $name, $id, $callback, $priority = 1000)
</code></pre>
<h3>Parameters</h3>
<ul>
<li><strong>$namespace</strong> - Usually the full namespace and class where the event originates.</li>
<li><strong>$name</strong> - Typically the method name where the event is triggered. If multiple events exist in the same method, this can be a custom identifier.</li>
<li><strong>$id</strong> - A unique identifier for the callback, often the class name (<code>__CLASS__</code>) registering the event.</li>
<li><strong>$callback</strong> - The function executed when the event is triggered.</li>
<li><strong>$priority</strong> - Determines execution order when multiple callbacks are registered. Lower numbers run first.</li>
</ul>
<h3>Examples</h3>
<h4>Add an item to the admin dashboard menu</h4>
<pre><code class="language-php">// add a new entry in the admin dashboard menu, used by plugins to add a link to plugin settings
Event::on('Vvveb\Controller\Base', 'init-menu', __CLASS__, function ($menu) use ($admin_path) {
	$menu['plugins']['items']['insert-scripts'] = [
		'name'     =&gt; __('Insert scripts'),
		'url'      =&gt; $admin_path . '?module=plugins/insert-scripts/settings',
		'icon-img' =&gt; PUBLIC_PATH . 'plugins/insert-scripts/insert-scripts.svg',
	];

	return [$menu];
});
</code></pre>
<h4>Modify post component results</h4>
<pre><code class="language-php">//__CLASS__ is usually used instead of  Vvveb\Plugins\ContentPlugin' for better code maintenance.
Event::on('Vvveb\Component\Post', 'results', __CLASS__, function ($results = false) {
	if ($results) {
		$results['content'] .= 'This is added at the end of all posts';
	}
	return [$results];
});
</code></pre>
<h4>Add Gravatar images to comments</h4>
<pre><code class="language-php">// __CLASS__ is usually used instead of 'Vvveb\Plugins\GravatarPlugin' for convenience
Event::on('Vvveb\Component\Comments', 'results', __CLASS__, function ($comments) {
	foreach ($comments['comments'] as &amp;$comment) {
		$comment['avatar'] = 'https://www.gravatar.com/avatar/' . md5(strtolower($comment['email']));
	}
	return [$comments];
});
</code></pre>
<hr />
<h2>Triggering Events</h2>
<p>To allow plugins to modify data or perform actions, trigger an event using:</p>
<pre><code class="language-php">function trigger($namespace, $name, $parameters)
</code></pre>
<h3>Parameters</h3>
<ul>
<li><strong>$namespace</strong> - Full namespace and class where the event is triggered.</li>
<li><strong>$name</strong> - Method name or custom event identifier.</li>
<li><strong>$parameters</strong> - One or more values passed to event callbacks.</li>
</ul>
<h3>Examples</h3>
<h4>Triggering inside a component’s <code>results()</code> method</h4>
<pre><code class="language-php">list($results) = Event::trigger(__CLASS__, __FUNCTION__, $results);
</code></pre>
<h4>Triggering with multiple parameters</h4>
<pre><code class="language-php">list($content, $language, $slug) = Event::trigger(__CLASS__, __FUNCTION__, $content, $language, $slug);
</code></pre>
<p>The returned values replace the originals, allowing plugins to modify them.</p>
<hr />
<h2>Removing Events</h2>
<p>To remove previously registered events, use:</p>
<pre><code class="language-php">function off($namespace, $name = false, $eventId = false)
</code></pre>
<h3>Usage</h3>
<ul>
<li>Remove a specific callback by its ID.</li>
<li>Remove all callbacks for a specific event.</li>
<li>Remove all callbacks for an entire namespace.</li>
</ul>
<h3>Examples</h3>
<pre><code class="language-php">// Remove a specific plugin callback
Event::off('Vvveb\Component\Post', 'results', 'Vvveb\Plugins\ContentPlugin');

// Remove all callbacks for the &quot;results&quot; event
Event::off('Vvveb\Component\Post', 'results');

// Remove all events in the Post component namespace
Event::off('Vvveb\Component\Post');
</code></pre>
<hr />
<h2>Inspecting Registered Events</h2>
<p>To list registered events, use:</p>
<pre><code class="language-php">function getEvents($namespace = false, $name = false)
</code></pre>
<h3>Examples</h3>
<pre><code class="language-php">// All callbacks for Post component &quot;results&quot; event
$events = Event::getEvents('Vvveb\Component\Post', 'results');

// All events in the Post component namespace
$events = Event::getEvents('Vvveb\Component\Post');

// All registered events in the system
$events = Event::getEvents();
</code></pre>
<hr />
<p>The event system is one of the most powerful extension mechanisms in Vvveb CMS, enabling plugins to modify data, extend functionality, and integrate seamlessly with core components.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="145">
			<title data-v-post-name="name">Plugin introduction</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/plugin-introduction</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:34 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Plugins extend Vvveb CMS by adding new features, modifying existing behavior, or integrating external services. Each plugin lives in its own directory under plugins/my-plugin-name. When distributing a]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>Plugins extend Vvveb CMS by adding new features, modifying existing behavior, or integrating external services.
Each plugin lives in its own directory under <code>plugins/my-plugin-name</code>. When distributing a plugin as a ZIP file, the archive must contain a <strong>single top‑level folder</strong> matching the plugin’s slug (e.g., <code>my-plugin-name/</code>).</p>
<p>A valid plugin must include at least one file:</p>
<pre><code>plugins/my-plugin-name/plugin.php
</code></pre>
<p>This file contains the plugin metadata header and the main plugin class.</p>
<hr />
<h2>Plugin Header</h2>
<p>Every plugin must begin with a comment block that defines its metadata.
This information is used by Vvveb to display the plugin in the admin interface and manage activation, settings, and updates.</p>
<pre><code class="language-php">&lt;?php
/*
Name: Insert Footer Header Scripts
Slug: insert-scripts
Category: tools
Url: http://www.vvveb.com
Description: Insert footer and header scripts such as analytics or widgets.
Thumb: insert-scripts.svg
Author: givanz
Version: 0.1
Author url: http://www.vvveb.com
Settings: /admin/?module=plugins/insert-scripts/settings
*/

use Vvveb\System\Event;

if (! defined('V_VERSION')) {
    die('Invalid request!');
}

class InsertScriptsPlugin {
    ...
}
?&gt;
</code></pre>
<h3>Notes</h3>
<ul>
<li><strong>Slug</strong> must match the plugin folder name exactly.</li>
<li><strong>Settings</strong> is optional and should point to the plugin’s admin settings page or controller.</li>
<li><strong>Thumb</strong> is the icon displayed in the admin plugin list.</li>
</ul>
<hr />
<h2>Plugin Folder Structure</h2>
<p>Plugins follow a structure similar to the CMS itself, allowing them to provide controllers, templates, SQL files, components, public assets, and optional installation scripts.</p>
<p>Not all folders are required; a plugin may include only what it needs.</p>
<p>A full plugin structure looks like this:</p>
<pre><code>my-plugin-name/
├── plugin.php                 # Main plugin file (required)
├── plugin.svg                 # Plugin thumbnail (optional)
│
├── app/                       # Frontend functionality
│   ├── controller/
│   │   └── index.php          # Optional frontend controller
│   ├── template/
│   │   ├── common.tpl         # Shared template
│   │   └── index.tpl          # Frontend page template
│   └── validate/
│       └── plugin-form.php    # Optional validation rules
│
├── admin/                     # Admin-side functionality
│   ├── controller/
│   │   └── index.php          # Admin controller (settings, tools)
│   ├── template/
│   │   └── settings.tpl       # Admin settings page template
│   └── validate/
│       └── plugin-form.php    # Optional validation rules
│
├── public/                    # Public assets
│   ├── admin/
│   │   └── settings.html      # HTML for admin settings UI
│   ├── app/
│   │   └── index.html         # HTML for frontend UI
│   ├── js/
│   │   └── plugin.js          # Optional JavaScript
│   └── css/
│       └── plugin.css         # Optional CSS
│
├── install/                   # Optional installation scripts
│   └── sql/
│       ├── mysql/plugin.sql   # MySQL schema
│       ├── pgsql/plugin.sql   # PostgreSQL schema
│       └── sqlite/plugin.sql  # SQLite schema
│
├── sql/                       # Runtime SQL queries
│   ├── mysql/plugin.sql
│   ├── pgsql/plugin.sql
│   └── sqlite/plugin.sql
│
├── component/
│   └── mycomponent.php        # Custom component provided by plugin
│
├── system/
│   ├── plugin.php             # Custom libraries or helpers
│   └── library.php            # Additional system utilities
│
└── vendor/                    # Third‑party libraries (optional)
</code></pre>
<hr />
<h2>How Plugins Integrate with Vvveb</h2>
<p>Plugins can extend Vvveb in several ways:</p>
<ul>
<li>Registering event listeners using the Event system.</li>
<li>Adding new components.</li>
<li>Adding admin menu items.</li>
<li>Creating new frontend or backend pages.</li>
<li>Injecting scripts, styles, or HTML into templates.</li>
<li>Providing custom SQL models.</li>
<li>Adding new validation rules.</li>
<li>Including public assets (JS, CSS, images).</li>
</ul>
<p>Because plugins follow the same MVC‑Component structure as the core CMS, they integrate cleanly and remain easy to maintain.</p>
<hr />
<p>Plugins are one of the most powerful parts of Vvveb’s architecture.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="65">
			<title data-v-post-name="name">Component posts</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-posts</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Posts component displays a list of posts anywhere in your theme. It supports pagination, filtering, sorting, taxonomy filtering, author filtering, and optional image galleries. This makes it suita]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Posts</strong> component displays a list of posts anywhere in your theme.
It supports pagination, filtering, sorting, taxonomy filtering, author filtering, and optional image galleries. This makes it suitable for blog pages, category pages, search results, or custom post listings.</p>
<hr />
<h2>Component Options</h2>
<p>Each option can be added as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>start</strong> - Starting offset for pagination. Default: <code>0</code>.</li>
<li><strong>limit</strong> - Number of posts to display. Default: <code>4</code>.</li>
<li><strong>page</strong> - Page number for pagination. Total pages = total posts ÷ limit.</li>
<li><strong>language_id</strong> - Language ID for post title and content. Default: current language.</li>
<li><strong>site_id</strong> - Site ID to load posts from. Default: current site.</li>
<li><strong>type</strong> - Post type. Default: <code>post</code>. Useful for custom post types.</li>
<li><strong>order</strong> - Field used for sorting. Options: <code>post_id</code>, <code>price</code>, <code>date_added</code>, <code>date_modified</code>.</li>
<li><strong>direction</strong> - Sorting direction. Options: <code>asc</code>, <code>desc</code>.</li>
<li><strong>taxonomy_item_id</strong> - Filter by taxonomy (category, tag, collection, etc.).</li>
<li><strong>include_image_gallery</strong> - Include post gallery images. Useful for hover image swap. Default: <code>true</code>.</li>
<li><strong>post_id</strong> - Filter by one or more post IDs. Accepts single value or comma‑separated list (e.g., <code>1,2,3</code>).</li>
<li><strong>search</strong> - Filter posts by title or content containing the search term.</li>
<li><strong>slug</strong> - Filter by post slug. Accepts single value or comma‑separated list (e.g., <code>slug-1,slug-2</code>).</li>
<li><strong>admin_id</strong> - Filter posts by author admin_id.</li>
<li><strong>username</strong> - Filter posts by author username (e.g., <code>admin</code>).</li>
<li><strong>date_format</strong> - Format for displaying the post creation date. Accepts any PHP date format or the keyword <code>human</code> for human‑friendly dates.</li>
<li><strong>sticky</strong> - Include sticky posts in the results.</li>
</ul>
<hr />
<h2>Component Properties</h2>
<p>Inside the component, the following repeatable post properties are available. Each post is wrapped in an element marked with <code>data-v-post</code>.</p>
<ul>
<li><strong>name</strong> - <code>data-v-post-name</code> - Post title.</li>
<li><strong>content</strong> - <code>data-v-post-content</code> - Post content.</li>
<li><strong>excerpt</strong> - <code>data-v-post-excerpt</code> - Post excerpt.</li>
<li><strong>status</strong> - <code>data-v-post-status</code> - Post status (<code>publish</code>, <code>disabled</code>, <code>scheduled</code>).</li>
<li><strong>image</strong> - <code>data-v-post-image</code> - Main post image.</li>
<li><strong>slug</strong> - <code>data-v-post-url</code> - Post slug.</li>
<li><strong>url</strong> - <code>data-v-post-url</code> - Post detail page URL.</li>
<li><strong>meta_keywords</strong> - <code>data-v-post-meta_keywords</code> - Post meta keywords.</li>
<li><strong>meta_description</strong> - <code>data-v-post-meta_description</code> - Post meta description.</li>
<li><strong>type</strong> - <code>data-v-post-type</code> - Post type, default is <code>post</code>.</li>
<li><strong>password</strong> - <code>data-v-post-password</code> - Post password if is password protected.</li>
<li><strong>comment_status</strong> - <code>data-v-post-comment_status</code> - Post comment status, if comments are allowed or disabled</li>
<li><strong>comment_count</strong> - <code>data-v-post-comment_count</code> - Number of comments on the post</li>
<li><strong>views</strong> - <code>data-v-post-comment_count</code> - Number of views on the post</li>
<li><strong>sort_order</strong> - <code>data-v-post-sort_order</code> - Post sort order.</li>
<li><strong>template</strong> - <code>data-v-post-template</code> - Template used to render the post if a different template is used.</li>
</ul>
<p>These properties repeat for each post returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;div data-v-component-posts 
     data-v-limit=&quot;10&quot; 
     data-v-page=&quot;2&quot;&gt;

    &lt;div data-v-post&gt;
        &lt;a href=&quot;#&quot; data-v-post-url&gt;
			&lt;span data-v-post-name&gt;Post name placeholder&lt;/span&gt;
		&lt;/a&gt;
        
        &lt;span data-v-post-excerpt&gt;Lorem ipsum&lt;/span&gt;
        &lt;span data-v-post-content&gt;Lorem ipsum&lt;/span&gt;
        
        &lt;img src=&quot;&quot; data-v-post-image&gt;
        
        &lt;a href=&quot;#&quot; data-v-post-url&gt;View post&lt;/a&gt;
    &lt;/div&gt;

&lt;/div&gt;
</code></pre>
<p>This example loads 10 posts from page 2, without including the image gallery. Each post is rendered inside the <code>data-v-post</code> block.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="66">
			<title data-v-post-name="name">Component checkout</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-checkout</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[
]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="68">
			<title data-v-post-name="name">Component comments</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-comments</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Post Comments Component renders a list of comments for a post. It is typically used on post detail pages, but it can also power recent‑comments widgets, sidebar lists, or threaded comment sectio]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Post Comments Component</strong> renders a list of comments for a post. It is typically used on post detail pages, but it can also power recent‑comments widgets, sidebar lists, or threaded comment sections.</p>
<p>Activate the component by adding:</p>
<pre><code>data-v-component-comments
</code></pre>
<p>The component supports filtering, sorting, pagination, and nested replies.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<h3><strong>Pagination &amp; Sorting</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>0</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Number of comments to display</td>
<td><code>4</code></td>
</tr>
<tr>
<td><strong>page</strong></td>
<td><code>data-v-page</code></td>
<td>Page number for pagination</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>order</strong></td>
<td><code>data-v-order</code></td>
<td>Sort field (<code>comment_id</code>, <code>user_id</code>, <code>created_at</code>, <code>updated_at</code>)</td>
<td><code>created_at</code></td>
</tr>
<tr>
<td><strong>direction</strong></td>
<td><code>data-v-direction</code></td>
<td>Sort direction (<code>asc</code>, <code>desc</code>)</td>
<td><code>desc</code></td>
</tr>
</tbody>
</table>
<h3><strong>Filtering</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-status</code></td>
<td>Comment status: <code>1</code> = published, <code>0</code> = pending, <code>2</code> = spam, <code>3</code> = trash</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>post_id</strong></td>
<td><code>data-v-post_id</code></td>
<td>Filter by post ID</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-slug</code></td>
<td>Filter by post slug</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-user_id</code></td>
<td>Filter by user ID</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<h3><strong>Additional Options</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for comment content and post title</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>post_title</strong></td>
<td><code>data-v-post_title</code></td>
<td>Include post title (useful for recent‑comments widgets)</td>
<td><code>false</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>Each comment is wrapped in:</p>
<pre><code>data-v-comment
</code></pre>
<p>The following fields are available inside each comment element.</p>
<h3><strong>Author Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>username</strong></td>
<td><code>data-v-comment-username</code></td>
<td>Username of the commenter</td>
</tr>
<tr>
<td><strong>email</strong></td>
<td><code>data-v-comment-email</code></td>
<td>Email address</td>
</tr>
<tr>
<td><strong>first_name</strong></td>
<td><code>data-v-comment-first_name</code></td>
<td>First name</td>
</tr>
<tr>
<td><strong>last_name</strong></td>
<td><code>data-v-comment-last_name</code></td>
<td>Last name</td>
</tr>
<tr>
<td><strong>display_name</strong></td>
<td><code>data-v-comment-display_name</code></td>
<td>Display name</td>
</tr>
<tr>
<td><strong>author</strong></td>
<td><code>data-v-comment-author</code></td>
<td>Full author name</td>
</tr>
<tr>
<td><strong>avatar</strong></td>
<td><code>data-v-comment-avatar</code></td>
<td>Avatar filename</td>
</tr>
<tr>
<td><strong>avatar_url</strong></td>
<td><code>data-v-comment-avatar_url</code></td>
<td>Full avatar URL</td>
</tr>
<tr>
<td><strong>bio</strong></td>
<td><code>data-v-comment-bio</code></td>
<td>Author biography</td>
</tr>
<tr>
<td><strong>subscribe</strong></td>
<td><code>data-v-comment-subscribe</code></td>
<td>Whether the user subscribed to replies</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Comment Metadata</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>comment_id</strong></td>
<td><code>data-v-comment-comment_id</code></td>
<td>Unique comment ID</td>
</tr>
<tr>
<td><strong>post_id</strong></td>
<td><code>data-v-comment-post_id</code></td>
<td>ID of the post the comment belongs to</td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-comment-user_id</code></td>
<td>ID of the user who posted the comment</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-comment-url</code></td>
<td>Author’s website URL</td>
</tr>
<tr>
<td><strong>ip</strong></td>
<td><code>data-v-comment-ip</code></td>
<td>IP address (if stored)</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-comment-status</code></td>
<td>Comment status</td>
</tr>
<tr>
<td><strong>votes</strong></td>
<td><code>data-v-comment-votes</code></td>
<td>Upvotes/downvotes</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>data-v-comment-type</code></td>
<td>Comment type (empty for standard comments)</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td><code>data-v-comment-parent_id</code></td>
<td>Parent comment ID (for threaded replies)</td>
</tr>
<tr>
<td><strong>level</strong></td>
<td><code>data-v-comment-level</code></td>
<td>Nesting level for threaded comments</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-comment-created_at</code></td>
<td>Creation timestamp</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-comment-updated_at</code></td>
<td>Last update timestamp</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Comment Content</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-comment-content</code></td>
<td>Comment text</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Post Information (Optional)</strong></h3>
<p>Displayed only when <code>data-v-post_title=&quot;true&quot;</code> is used.</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-comment-name</code></td>
<td>Title of the post the comment belongs to</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-comment-slug</code></td>
<td>Slug of the post the comment belongs to</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-component-comments data-v-post_id=&quot;url&quot;&gt;

  &lt;ol data-v-if=&quot;count &gt; 0&quot;&gt;

    &lt;li data-v-comment&gt;

      &lt;div class=&quot;comment-wrap&quot;&gt;

        &lt;figure class=&quot;author-avatar me-2&quot;&gt;
          &lt;img data-v-comment-avatar_url
               alt=&quot;user&quot;
               width=&quot;60&quot;
               loading=&quot;lazy&quot;
               src=&quot;/media/vvveb.svg&quot; 
               data-v-if=&quot;comment.avatar_url&quot;&gt;
        &lt;/figure&gt;

        &lt;div class=&quot;comment-author&quot;&gt;

          &lt;a rel=&quot;external nofollow ugc&quot; data-v-if=&quot;comment.url&quot;&gt;
            &lt;span data-v-comment-author&gt;John Doe&lt;&lt;/span&gt;
          &lt;/a&gt;


	&lt;div class=&quot;comment-meta&quot;&gt;
	  &lt;span data-v-comment-created_at data-filter-friendly_date&gt;3 year ago&lt;/span&gt;
	&lt;/div&gt;


        &lt;/div&gt;

      &lt;/div&gt;

		&lt;div data-v-comment-content&gt;This is an approved comment.&lt;/div&gt;

      &lt;div class=&quot;reply&quot;&gt;
        &lt;a href=&quot;#comment-form&quot;
           class=&quot;reply-btn&quot;
           data-v-vvveb-action=&quot;replyTo&quot;
           data-comment_id
           data-comment_author&gt;
          Reply &lt;i class=&quot;la la-reply&quot;&gt;&lt;/i&gt;
        &lt;/a&gt;
      &lt;/div&gt;

    &lt;/li&gt;

  &lt;/ol&gt;

  &lt;div class=&quot;alert&quot; role=&quot;alert&quot; data-v-if-not=&quot;this.default_comment_status&quot;&gt;
    &lt;div data-v-notification-text&gt;
      &lt;span&gt;Comments are closed&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

</code></pre>
<p>This example displays a threaded comment list with avatars, author names, timestamps, content, and reply actions.</p>
<h1><strong>Post Comment Form Component</strong></h1>
<p>The <strong>Comment Form</strong> handles comment submission on post pages.
It works together with the <strong>Post Comments Component</strong>, allowing users to submit new comments or reply to existing ones. The form supports logged‑in users, anonymous commenters (if enabled), CSRF protection, and threaded replies.</p>
<p>To use javascript to post the comment without refreshing the page add the following attributes:</p>
<pre><code>data-v-vvveb-action=&quot;addComment&quot;
data-v-vvveb-on=&quot;submit&quot;
</code></pre>
<p>These attributes instruct Vvveb CMS to process the form submission through javascript fetch.</p>
<hr />
<h2><strong>How the Comment Form Works</strong></h2>
<p>The form posts data to the current page and is intercepted by the Vvveb action handler. The handler:</p>
<ul>
<li>Validates required fields</li>
<li>Checks CSRF token</li>
<li>Determines whether the user is logged in or anonymous</li>
<li>Creates a new comment in the database</li>
<li>Assigns the comment to the correct post</li>
<li>Handles threaded replies via <code>parent_id</code></li>
<li>Returns success or error notifications</li>
</ul>
<p>If comments require moderation, the submitted comment may be stored with <code>status = 0</code> (pending).</p>
<hr />
<h2><strong>Form Fields</strong></h2>
<p>The form includes a mix of visible and hidden fields. These fields are required for proper comment submission.</p>
<h3><strong>Hidden System Fields</strong></h3>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>post_id</strong></td>
<td>Identifies the post the comment belongs to</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td>Post slug (used for redirects and validation)</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td>ID of the parent comment (0 for top‑level comments)</td>
</tr>
<tr>
<td><strong>csrf</strong></td>
<td>CSRF token for security</td>
</tr>
<tr>
<td><strong>firstname-empty</strong></td>
<td>Honeypot anti‑spam field (must remain empty)</td>
</tr>
<tr>
<td><strong>subject-empty</strong></td>
<td>Honeypot anti‑spam field</td>
</tr>
<tr>
<td><strong>lastname-empty</strong></td>
<td>Honeypot anti‑spam field</td>
</tr>
</tbody>
</table>
<p>Honeypot fields help block bots without affecting real users.</p>
<hr />
<h3><strong>User Identity Fields</strong></h3>
<p>These fields are shown only when the user is <strong>not logged in</strong>:</p>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>author</strong></td>
<td>Yes</td>
<td>Name of the commenter</td>
</tr>
<tr>
<td><strong>email</strong></td>
<td>Yes</td>
<td>Email address of the commenter</td>
</tr>
</tbody>
</table>
<p>When the user is logged in, these fields are omitted because the system already knows the user’s identity.</p>
<hr />
<h3><strong>Comment Content</strong></h3>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>content</strong></td>
<td>Yes</td>
<td>The actual comment text</td>
</tr>
</tbody>
</table>
<p>This is the main body of the comment.</p>
<hr />
<h2><strong>Replying to Comments</strong></h2>
<p>The reply links in the comment list use:</p>
<pre><code>data-v-vvveb-action=&quot;replyTo&quot;
</code></pre>
<p>This action:</p>
<ul>
<li>Scrolls to the comment form</li>
<li>Sets the hidden <code>parent_id</code> field to the ID of the comment being replied to</li>
<li>Optionally displays the name of the user being replied to</li>
</ul>
<p>This enables threaded/nested comments.</p>
<hr />
<h2><strong>Anonymous Comments</strong></h2>
<p>The form includes:</p>
<pre><code>data-v-if=&quot;this.global.user_id || this.anonymous_comments&quot;
</code></pre>
<p>This means:</p>
<ul>
<li>If the user is logged in → show the form</li>
<li>If the user is not logged in but anonymous comments are allowed → show the form</li>
<li>Otherwise → hide the form</li>
</ul>
<p>Anonymous comment settings are controlled in the site configuration.</p>
<hr />
<h2><strong>Validation &amp; Security</strong></h2>
<p>The comment form includes several built‑in protections:</p>
<ul>
<li><strong>CSRF token</strong> (<code>data-v-csrf</code>)</li>
<li><strong>Honeypot fields</strong> (<code>firstname-empty</code>, <code>subject-empty</code>, <code>lastname-empty</code>)</li>
<li><strong>Server‑side validation</strong> of required fields</li>
<li><strong>Status filtering</strong> (pending, spam, trash)</li>
</ul>
<p>If moderation is enabled, comments may not appear immediately.</p>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;form id=&quot;comment-form&quot;
      method=&quot;post&quot;
      action=&quot;&quot;
      data-v-vvveb-action=&quot;addComment&quot;
      data-v-vvveb-on=&quot;submit&quot;
      data-v-if=&quot;this.global.user_id || this.anonymous_comments&quot;&gt;

  &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; data-v-post-post_id&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;slug&quot; data-v-post-slug&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;parent_id&quot; value=&quot;0&quot;&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;csrf&quot; data-v-csrf&gt;

  &lt;!-- Honeypot anti-spam fields --&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;firstname-empty&quot;&gt;
  &lt;input type=&quot;text&quot; class=&quot;visually-hidden&quot; name=&quot;lastname-empty&quot; tabindex=&quot;-1&quot;&gt;
  &lt;input type=&quot;text&quot; class=&quot;d-none&quot; name=&quot;subject-empty&quot;&gt;

  &lt;!-- Anonymous user fields --&gt;
  &lt;div data-v-if-not=&quot;this.global.user_id&quot;&gt;
    &lt;div class=&quot;mb-3&quot;&gt;
      &lt;label class=&quot;form-label&quot;&gt;Name&lt;/label&gt;
      &lt;input type=&quot;text&quot; name=&quot;author&quot; class=&quot;form-control&quot; required&gt;
    &lt;/div&gt;

    &lt;div class=&quot;mb-3&quot;&gt;
      &lt;label class=&quot;form-label&quot;&gt;Email address&lt;/label&gt;
      &lt;input type=&quot;email&quot; name=&quot;email&quot; class=&quot;form-control&quot; required&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- Comment text --&gt;
  &lt;div class=&quot;mb-3&quot;&gt;
    &lt;textarea name=&quot;content&quot; rows=&quot;5&quot; class=&quot;form-control&quot; placeholder=&quot;Comment&quot; required&gt;&lt;/textarea&gt;
  &lt;/div&gt;

  &lt;!-- Submit --&gt;
  &lt;button type=&quot;submit&quot; class=&quot;btn btn-primary btn-submit&quot;&gt;
    &lt;span class=&quot;loading d-none&quot;&gt;
      &lt;span class=&quot;spinner-border spinner-border-sm&quot;&gt;&lt;/span&gt;
      &lt;span&gt;Posting...&lt;/span&gt;
    &lt;/span&gt;

    &lt;span class=&quot;button-text&quot;&gt;
      &lt;span&gt;Post comment&lt;/span&gt;
      &lt;i class=&quot;la la-long-arrow-alt-right ms-1&quot;&gt;&lt;/i&gt;
    &lt;/span&gt;
  &lt;/button&gt;

&lt;/form&gt;
</code></pre>
<p>This example includes all required fields, anonymous user handling, CSRF protection, and reply support.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="70">
			<title data-v-post-name="name">Component categories</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-categories</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Categories Component displays a recursive, nested list of categories or tags. It can be used for sidebars, navigation menus, product filters, blog taxonomies, or any place where hierarchical categ]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Categories Component</strong> displays a recursive, nested list of categories or tags.
It can be used for sidebars, navigation menus, product filters, blog taxonomies, or any place where hierarchical category structures are needed.</p>
<p>The component supports filtering, pagination, taxonomy selection, and custom post types.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>All options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<p>Below are the available options:</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td>Starting offset for pagination</td>
<td><code>0</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td>Number of categories to display</td>
<td><code>7</code></td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td>Load categories from a specific site</td>
<td>Current site</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td>Load categories for a specific language</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>order</strong></td>
<td>Sorting rules (e.g., <code>url</code>, <code>price asc</code>)</td>
<td>None</td>
</tr>
<tr>
<td><strong>taxonomy_id</strong></td>
<td>Filter by taxonomy/category ID</td>
<td>None</td>
</tr>
<tr>
<td><strong>post_id</strong></td>
<td>Show only categories assigned to a specific post</td>
<td>None</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td>Filter by parent category (<code>0</code> = top‑level)</td>
<td>None</td>
</tr>
<tr>
<td><strong>search</strong></td>
<td>Filter categories by text</td>
<td>None</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>categories</code> or <code>tags</code></td>
<td><code>categories</code></td>
</tr>
<tr>
<td><strong>post_type</strong></td>
<td>Filter by post type taxonomy (for custom posts)</td>
<td><code>post</code></td>
</tr>
<tr>
<td><strong>count</strong></td>
<td>Include number of posts in each category (<code>true/false</code>)</td>
<td><code>false</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>Inside the component, categories are rendered using:</p>
<ul>
<li><code>data-v-cats</code> — container for the list</li>
<li><code>data-v-cat</code> — repeatable element for each category</li>
</ul>
<p>Each category exposes the following properties:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-cat-name</code></td>
<td>Category name</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-cat-slug</code></td>
<td>URL slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-cat-content</code></td>
<td>Category description/content</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-cat-url</code></td>
<td>Category URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td><code>data-v-cat-image</code></td>
<td>Category image</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td><code>data-v-cat-parent_id</code></td>
<td>Parent category ID (<code>0</code> = top level)</td>
</tr>
<tr>
<td><strong>item_id</strong></td>
<td><code>data-v-cat-item_id</code></td>
<td>Category ID</td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-cat-sort_order</code></td>
<td>Sort order</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-cat-status</code></td>
<td><code>1</code> = enabled, <code>0</code> = disabled</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-cat-language_id</code></td>
<td>Language ID for multilingual content</td>
</tr>
</tbody>
</table>
<p>These properties can be used inside your HTML to build custom layouts.</p>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div class=&quot;card&quot; 
     data-v-component-categories=&quot;sidebar&quot; 
     data-v-type=&quot;categories&quot; 
     data-v-limit=&quot;1000&quot; 
     data-v-post_type=&quot;product&quot;&gt;

  &lt;div class=&quot;card-body&quot;&gt;
    &lt;h6 class=&quot;card-title&quot;&gt;Categories&lt;/h6&gt;

    &lt;ul data-v-cats&gt;
      &lt;li data-v-cat&gt;
        &lt;input type=&quot;checkbox&quot; id=&quot;c1&quot; data-v-if=&quot;category.children &gt; 0&quot; /&gt;
        &lt;label for=&quot;c1&quot; data-v-if=&quot;category.children &gt; 0&quot;&gt;
          &lt;a data-v-cat-url data-v-cat-name&gt;&lt;/a&gt;
        &lt;/label&gt;

        &lt;a data-v-if=&quot;category.children = 0&quot; 
           data-v-cat-url 
           data-v-cat-name&gt;&lt;/a&gt;
      &lt;/li&gt;

      &lt;li data-v-cat&gt;
        &lt;a data-v-cat-url&gt;
          &lt;span data-v-cat-name&gt;&lt;/span&gt;
        &lt;/a&gt;
      &lt;/li&gt;

      &lt;li data-v-cat&gt;
        &lt;a data-v-cat-url&gt;
          &lt;span data-v-cat-name&gt;&lt;/span&gt;
        &lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="71">
			<title data-v-post-name="name">Component orders</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-orders</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Orders Component displays a list of customer orders. It is typically used on the My Orders page inside a customer account, or in any template where you need to show order history, order summaries,]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Orders Component</strong> displays a list of customer orders. It is typically used on the <strong>My Orders</strong> page inside a customer account, or in any template where you need to show order history, order summaries, or filtered order lists.</p>
<p>Activate the component by adding:</p>
<pre><code>data-v-component-orders
</code></pre>
<p>The component supports filtering, sorting, pagination, and multisite/multilanguage setups.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax. These control which orders are loaded and how they are filtered or sorted.</p>
<h3><strong>Filtering, Pagination &amp; Sorting</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>0</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Number of orders to display; can be a number or <code>url</code> to read from GET</td>
<td><code>4</code></td>
</tr>
<tr>
<td><strong>order_by</strong></td>
<td><code>data-v-order_by</code></td>
<td>Field to sort by (<code>order_id</code>, <code>created_at</code>, etc.)</td>
<td><code>order_id</code></td>
</tr>
<tr>
<td><strong>direction</strong></td>
<td><code>data-v-direction</code></td>
<td>Sort direction (<code>ASC</code> or <code>DESC</code>)</td>
<td><code>DESC</code></td>
</tr>
<tr>
<td><strong>search</strong></td>
<td><code>data-v-search</code></td>
<td>Search by customer first/last name</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<h3><strong>Customer &amp; Identity Filters</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-user_id</code></td>
<td>Filter by customer ID</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>email</strong></td>
<td><code>data-v-email</code></td>
<td>Filter by customer email</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>phone_number</strong></td>
<td><code>data-v-phone_number</code></td>
<td>Filter by customer phone</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<h3><strong>Order Status Filters</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>order_status</strong></td>
<td><code>data-v-order_status</code></td>
<td>Filter by order status code (e.g., <code>pending</code>)</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>order_status_id</strong></td>
<td><code>data-v-order_status_id</code></td>
<td>Filter by order status ID</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>payment_status</strong></td>
<td><code>data-v-payment_status</code></td>
<td>Filter by payment status code</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>payment_status_id</strong></td>
<td><code>data-v-payment_status_id</code></td>
<td>Filter by payment status ID</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>shipping_status</strong></td>
<td><code>data-v-shipping_status</code></td>
<td>Filter by shipping status code (e.g., <code>not_fulfilled</code>)</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>shipping_status_id</strong></td>
<td><code>data-v-shipping_status_id</code></td>
<td>Filter by shipping status ID</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<h3><strong>Localization &amp; Media</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for product names, order statuses, descriptions</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-site_id</code></td>
<td>Site ID for multisite setups</td>
<td>Current site</td>
</tr>
<tr>
<td><strong>image_size</strong></td>
<td><code>data-v-image_size</code></td>
<td>Product image size (<code>xlarge</code>, <code>large</code>, <code>medium</code>, <code>thumb</code>)</td>
<td><code>medium</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Order Properties</strong></h2>
<p>Each order is wrapped in:</p>
<pre><code>data-v-order
</code></pre>
<p>Inside it, the following fields are available.</p>
<h3><strong>General Order Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>order_id</strong></td>
<td><code>data-v-order-order_id</code></td>
<td>Internal order ID</td>
</tr>
<tr>
<td><strong>customer_order_id</strong></td>
<td><code>data-v-order-customer_order_id</code></td>
<td>Public customer‑facing order ID Eg:I-26-03-6-1-UPDQGK9B6EKP-26</td>
</tr>
<tr>
<td><strong>invoice_no</strong></td>
<td><code>data-v-order-invoice_no</code></td>
<td>Invoice number</td>
</tr>
<tr>
<td><strong>invoice_prefix</strong></td>
<td><code>data-v-order-invoice_prefix</code></td>
<td>Invoice prefix</td>
</tr>
<tr>
<td><strong>order-url</strong></td>
<td><code>data-v-order-url</code></td>
<td>URL to the order details page</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-order-site_id</code></td>
<td>Site where the order was placed</td>
</tr>
<tr>
<td><strong>site_name</strong></td>
<td><code>data-v-order-site_name</code></td>
<td>Site name</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-order-created_at</code></td>
<td>Order creation date</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-order-updated_at</code></td>
<td>Last update date</td>
</tr>
<tr>
<td><strong>notes</strong></td>
<td><code>data-v-order-notes</code></td>
<td>Customer notes</td>
</tr>
<tr>
<td><strong>remote_ip</strong></td>
<td><code>data-v-order-remote_ip</code></td>
<td>Customer IP address</td>
</tr>
<tr>
<td><strong>forwarded_for_ip</strong></td>
<td><code>data-v-order-forwarded_for_ip</code></td>
<td>Forwarded IP (proxy)</td>
</tr>
<tr>
<td><strong>user_agent</strong></td>
<td><code>data-v-order-user_agent</code></td>
<td>Browser user agent</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Customer Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-order-user_id</code></td>
</tr>
<tr>
<td><strong>user_group_id</strong></td>
<td><code>data-v-order-user_group_id</code></td>
</tr>
<tr>
<td><strong>first_name</strong></td>
<td><code>data-v-order-first_name</code></td>
</tr>
<tr>
<td><strong>last_name</strong></td>
<td><code>data-v-order-last_name</code></td>
</tr>
<tr>
<td><strong>email</strong></td>
<td><code>data-v-order-email</code></td>
</tr>
<tr>
<td><strong>phone_number</strong></td>
<td><code>data-v-order-phone_number</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Billing Address</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>billing_first_name</strong></td>
<td><code>data-v-order-billing_first_name</code></td>
</tr>
<tr>
<td><strong>billing_last_name</strong></td>
<td><code>data-v-order-billing_last_name</code></td>
</tr>
<tr>
<td><strong>billing_company</strong></td>
<td><code>data-v-order-billing_company</code></td>
</tr>
<tr>
<td><strong>billing_address_1</strong></td>
<td><code>data-v-order-billing_address_1</code></td>
</tr>
<tr>
<td><strong>billing_address_2</strong></td>
<td><code>data-v-order-billing_address_2</code></td>
</tr>
<tr>
<td><strong>billing_city</strong></td>
<td><code>data-v-order-billing_city</code></td>
</tr>
<tr>
<td><strong>billing_post_code</strong></td>
<td><code>data-v-order-billing_post_code</code></td>
</tr>
<tr>
<td><strong>billing_country_id</strong></td>
<td><code>data-v-order-billing_country_id</code></td>
</tr>
<tr>
<td><strong>billing_country</strong></td>
<td><code>data-v-order-billing_country</code></td>
</tr>
<tr>
<td><strong>billing_region</strong></td>
<td><code>data-v-order-billing_region</code></td>
</tr>
<tr>
<td><strong>billing_region_id</strong></td>
<td><code>data-v-order-billing_region_id</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Shipping Address</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>shipping_first_name</strong></td>
<td><code>data-v-order-shipping_first_name</code></td>
</tr>
<tr>
<td><strong>shipping_last_name</strong></td>
<td><code>data-v-order-shipping_last_name</code></td>
</tr>
<tr>
<td><strong>shipping_company</strong></td>
<td><code>data-v-order-shipping_company</code></td>
</tr>
<tr>
<td><strong>shipping_address_1</strong></td>
<td><code>data-v-order-shipping_address_1</code></td>
</tr>
<tr>
<td><strong>shipping_address_2</strong></td>
<td><code>data-v-order-shipping_address_2</code></td>
</tr>
<tr>
<td><strong>shipping_city</strong></td>
<td><code>data-v-order-shipping_city</code></td>
</tr>
<tr>
<td><strong>shipping_post_code</strong></td>
<td><code>data-v-order-shipping_post_code</code></td>
</tr>
<tr>
<td><strong>shipping_country_id</strong></td>
<td><code>data-v-order-shipping_country_id</code></td>
</tr>
<tr>
<td><strong>shipping_region</strong></td>
<td><code>data-v-order-shipping_region</code></td>
</tr>
<tr>
<td><strong>shipping_region_group_id</strong></td>
<td><code>data-v-order-shipping_region_group_id</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Payment Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>payment_method</strong></td>
<td><code>data-v-order-payment_method</code></td>
<td>Payment method code</td>
</tr>
<tr>
<td><strong>payment_title</strong></td>
<td><code>data-v-order-payment_title</code></td>
<td>Payment method name</td>
</tr>
<tr>
<td><strong>payment_status</strong></td>
<td><code>data-v-order-payment_status</code></td>
<td>Payment status</td>
</tr>
<tr>
<td><strong>payment_status_id</strong></td>
<td><code>data-v-order-payment_status_id</code></td>
<td>Payment status ID</td>
</tr>
<tr>
<td><strong>payment_data</strong></td>
<td><code>data-v-order-payment_data-*</code></td>
<td>Additional payment plugin data</td>
</tr>
</tbody>
</table>
<h4>Payment Data Object</h4>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-order-payment_data-title</code></td>
</tr>
<tr>
<td><strong>description</strong></td>
<td><code>data-v-order-payment_data-description</code></td>
</tr>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-order-payment_data-name</code></td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-order-payment_data-status</code></td>
</tr>
<tr>
<td><strong>region_id</strong></td>
<td><code>data-v-order-payment_data-region_id</code></td>
</tr>
<tr>
<td><strong>region_group_id</strong></td>
<td><code>data-v-order-payment_data-region_group_id</code></td>
</tr>
<tr>
<td><strong>payment_status_id</strong></td>
<td><code>data-v-order-payment_data-payment_status_id</code></td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-order-payment_data-sort_order</code></td>
</tr>
<tr>
<td><strong>tax_type_id</strong></td>
<td><code>data-v-order-payment_data-tax_type_id</code></td>
</tr>
<tr>
<td><strong>cost</strong></td>
<td><code>data-v-order-payment_data-cost</code></td>
</tr>
<tr>
<td><strong>base-weight</strong></td>
<td><code>data-v-order-payment_data-weight</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Shipping Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>shipping_method</strong></td>
<td><code>data-v-order-shipping_method</code></td>
<td>Shipping method code</td>
</tr>
<tr>
<td><strong>shipping_title</strong></td>
<td><code>data-v-order-shipping_title</code></td>
<td>Shipping method name</td>
</tr>
<tr>
<td><strong>shipping_description</strong></td>
<td><code>data-v-order-shipping_description</code></td>
<td>Description</td>
</tr>
<tr>
<td><strong>shipping_status</strong></td>
<td><code>data-v-order-shipping_status</code></td>
<td>Shipping status</td>
</tr>
<tr>
<td><strong>shipping_status_id</strong></td>
<td><code>data-v-order-shipping_status_id</code></td>
<td>Status ID</td>
</tr>
<tr>
<td><strong>shipping_data</strong></td>
<td><code>data-v-order-shipping_data-*</code></td>
<td>Additional shipping plugin data</td>
</tr>
</tbody>
</table>
<h4>Shipping Data Object</h4>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-order-shipping_data-title</code></td>
</tr>
<tr>
<td><strong>description</strong></td>
<td><code>data-v-order-shipping_data-description</code></td>
</tr>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-order-shipping_data-name</code></td>
</tr>
<tr>
<td><strong>region_id</strong></td>
<td><code>data-v-order-shipping_data-region_id</code></td>
</tr>
<tr>
<td><strong>region_group_id</strong></td>
<td><code>data-v-order-shipping_data-region_group_id</code></td>
</tr>
<tr>
<td><strong>shipping_status_id</strong></td>
<td><code>data-v-order-shipping_data-shipping_status_id</code></td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-order-shipping_data-sort_order</code></td>
</tr>
<tr>
<td><strong>tax_type_id</strong></td>
<td><code>data-v-order-shipping_data-tax_type_id</code></td>
</tr>
<tr>
<td><strong>cost</strong></td>
<td><code>data-v-order-shipping_data-cost</code></td>
</tr>
<tr>
<td><strong>base-weight</strong></td>
<td><code>data-v-order-shipping_data-weight</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Order Totals</strong></h2>
<p>Each total row is wrapped in:</p>
<pre><code>data-v-order-total
</code></pre>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>namespace</strong></td>
<td><code>data-v-total-namespace</code></td>
<td>Group: <code>tax</code>, <code>coupon</code>, <code>total</code>, etc.</td>
</tr>
<tr>
<td><strong>key</strong></td>
<td><code>data-v-total-key</code></td>
<td>Unique key (e.g., <code>tax.1</code>, <code>coupon.3</code>, <code>sub_total</code>)</td>
</tr>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-order-total-title</code></td>
<td>Label shown to the user</td>
</tr>
<tr>
<td><strong>value</strong></td>
<td><code>data-v-order-total-value</code></td>
<td>Numeric value</td>
</tr>
<tr>
<td><strong>value_formatted</strong></td>
<td><code>data-v-order-total-value_formatted</code></td>
<td>Value formatted with currency</td>
</tr>
<tr>
<td><strong>text</strong></td>
<td><code>data-v-order-total-text</code></td>
<td>Optional explanatory text</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Products List</strong></h2>
<p>Each product in the order is wrapped in:</p>
<pre><code>data-v-order-product
</code></pre>
<h3><strong>Product Properties</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-order-product-name</code></td>
<td>Product name</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-order-product-slug</code></td>
<td>Product slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-order-product-content</code></td>
<td>Full description</td>
</tr>
<tr>
<td><strong>excerpt</strong></td>
<td><code>data-v-order-product-excerpt</code></td>
<td>Short description</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-order-product-url</code></td>
<td>Product detail page URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td><code>data-v-order-product-image</code></td>
<td>Featured image</td>
</tr>
<tr>
<td><strong>images</strong></td>
<td><code>data-v-order-product-images</code></td>
<td>Gallery images</td>
</tr>
<tr>
<td><strong>quantity</strong></td>
<td><code>data-v-order-product-quantity</code></td>
<td>Quantity in order</td>
</tr>
<tr>
<td><strong>price</strong></td>
<td><code>data-v-order-product-price</code></td>
<td>Price without tax</td>
</tr>
<tr>
<td><strong>price_tax</strong></td>
<td><code>data-v-order-product-price_tax</code></td>
<td>Price including tax</td>
</tr>
<tr>
<td><strong>price_formatted</strong></td>
<td><code>data-v-order-product-price_formatted</code></td>
<td>Price formatted with currency</td>
</tr>
<tr>
<td><strong>price_tax_formatted</strong></td>
<td><code>data-v-order-product-price_tax_formatted</code></td>
<td>Price including tax, formatted</td>
</tr>
<tr>
<td><strong>old_price</strong></td>
<td><code>data-v-order-product-old_price</code></td>
<td>Price before discount</td>
</tr>
<tr>
<td><strong>old_price_tax</strong></td>
<td><code>data-v-order-product-old_price_tax</code></td>
<td>Old price including tax</td>
</tr>
<tr>
<td><strong>old_price_tax_formatted</strong></td>
<td><code>data-v-order-product-old_price_tax_formatted</code></td>
<td>Old price formatted</td>
</tr>
<tr>
<td><strong>stock_quantity</strong></td>
<td><code>data-v-order-product-stock_quantity</code></td>
<td>Units in stock</td>
</tr>
<tr>
<td><strong>stock_status</strong></td>
<td><code>data-v-order-product-stock_status_id</code></td>
<td>Stock status</td>
</tr>
<tr>
<td><strong>product_id</strong></td>
<td><code>data-v-order-product-product_id</code></td>
<td>Product ID</td>
</tr>
<tr>
<td><strong>product_variant_id</strong></td>
<td><code>data-v-order-product-product_variant_id</code></td>
<td>Variant ID</td>
</tr>
<tr>
<td><strong>has_variants</strong></td>
<td><code>data-v-order-product-has_variants</code></td>
<td>Whether product has variants</td>
</tr>
<tr>
<td><strong>add_order_url</strong></td>
<td><code>data-v-order-product-add_order_url</code></td>
<td>Add‑to‑order URL</td>
</tr>
<tr>
<td><strong>buy_url</strong></td>
<td><code>data-v-order-product-buy_url</code></td>
<td>Direct buy URL</td>
</tr>
<tr>
<td><strong>remove_url</strong></td>
<td><code>data-v-order-product-remove_url</code></td>
<td>Remove from order URL</td>
</tr>
<tr>
<td><strong>manufacturer_name</strong></td>
<td><code>data-v-order-product-manufacturer_name</code></td>
<td>Manufacturer</td>
</tr>
<tr>
<td><strong>vendor_name</strong></td>
<td><code>data-v-order-product-vendor_name</code></td>
<td>Vendor</td>
</tr>
<tr>
<td><strong>subscription_name</strong></td>
<td><code>data-v-order-product-subscription_name</code></td>
<td>Subscription plan name</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-order-product-created_at</code></td>
<td>Creation date</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-order-product-updated_at</code></td>
<td>Last update</td>
</tr>
<tr>
<td><strong>pubDate</strong></td>
<td><code>data-v-order-product-pubDate</code></td>
<td>Publish date (RSS format)</td>
</tr>
<tr>
<td><strong>modDate</strong></td>
<td><code>data-v-order-product-modDate</code></td>
<td>Modification date (RSS format)</td>
</tr>
</tbody>
</table>
<p>Product options, variants, and subscription details are also available as nested repeatables.</p>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-component-orders data-v-user_id=&quot;url&quot;&gt;            
&lt;table&gt;
  &lt;thead&gt;
	&lt;tr&gt;
	  &lt;td class=&quot;text-center&quot;&gt;Order id&lt;/td&gt;
	  &lt;td class=&quot;text-center&quot;&gt;Client&lt;/td&gt;
	  &lt;td class=&quot;text-center&quot;&gt;Status&lt;/td&gt;
	  &lt;td class=&quot;text-center&quot;&gt;Total&lt;/td&gt;
	  &lt;td class=&quot;text-center&quot;&gt;Date added&lt;/td&gt;
	  &lt;td class=&quot;text-center&quot;&gt;Actions&lt;/td&gt;
	&lt;/tr&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
	&lt;tr data-v-order&gt;
	  &lt;td class=&quot;text-center&quot;&gt;
		&lt;span&gt;#&lt;/span&gt;
		&lt;span data-v-order-order_id&gt;&lt;/span&gt;
	  &lt;/td&gt;

	  &lt;td class=&quot;text-center&quot;&gt;
		&lt;span data-v-order-first_name data-filter-capitalize&gt;John&lt;/span&gt;
		&lt;span data-v-order-last_name data-filter-capitalize&gt;Doe&lt;/span&gt;
	  &lt;/td&gt;

	  &lt;td class=&quot;text-center&quot;&gt;
		&lt;span data-v-order-status&gt;&lt;/span&gt;
	  &lt;/td&gt;

	  &lt;td class=&quot;text-center&quot;&gt;
		&lt;span data-v-order-total&gt;3457.8000&lt;/span&gt;
	  &lt;/td&gt;

	  &lt;td class=&quot;text-center&quot;&gt;
		&lt;span data-v-order-created_at data-filter-friendly_date&gt;5 hour ago&lt;/span&gt;
	  &lt;/td&gt;

	  &lt;td class=&quot;text-center&quot;&gt;
		&lt;a href=&quot;/user/order/UPDQGK9B6EKP-26&quot; title=&quot;View&quot; data-v-order-url&gt;
		  &lt;i class=&quot;la la-eye&quot;&gt;&lt;/i&gt;
		&lt;/a&gt;
	  &lt;/td&gt;
	&lt;/tr&gt;                             
  &lt;/tbody&gt;
&lt;/table&gt;
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="73">
			<title data-v-post-name="name">Component product</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-product</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[Product Component 
The Product Component renders one or more products on any page or template. Use it to display a single product detail, a product card, or a small product list (related products, fea]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[<h3>Product Component</h3>
<p>The <strong>Product Component</strong> renders one or more products on any page or template. Use it to display a single product detail, a product card, or a small product list (related products, featured items, etc.). Add the component by placing the <code>data-v-component-product</code> attribute on a container element.</p>
<hr />
<h3>Component Options</h3>
<p>Add options as HTML attributes using the <strong><code>data-v-*</code></strong> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th align="right">Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>product id</strong></td>
<td align="right"><code>data-v-product_id</code></td>
<td>Load a specific product by ID</td>
<td>URL detection (page param)</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td align="right"><code>data-v-slug</code></td>
<td>Load a product by slug</td>
<td>URL detection (page param)</td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td align="right"><code>data-v-limit</code></td>
<td>Number of products to return</td>
<td><code>4</code></td>
</tr>
<tr>
<td><strong>page</strong></td>
<td align="right"><code>data-v-page</code></td>
<td>Page number for pagination</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>language id</strong></td>
<td align="right"><code>data-v-language_id</code></td>
<td>Language for product name/content</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>site id</strong></td>
<td align="right"><code>data-v-site_id</code></td>
<td>Site to load products from</td>
<td>Current site</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td align="right"><code>data-v-type</code></td>
<td>Product type (custom types supported)</td>
<td><code>product</code></td>
</tr>
<tr>
<td><strong>status</strong></td>
<td align="right"><code>data-v-status</code></td>
<td><code>1</code> = enabled, <code>0</code> = disabled</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>user group id</strong></td>
<td align="right"><code>data-v-user_group_id</code></td>
<td>Use group pricing rules</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>product variant id</strong></td>
<td align="right"><code>data-v-product_variant_id</code></td>
<td>Show a specific variant by default</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>include variants</strong></td>
<td align="right"><code>data-v-variant</code></td>
<td>Include variant data (<code>true/false</code>)</td>
<td><code>false</code></td>
</tr>
<tr>
<td><strong>include promotion</strong></td>
<td align="right"><code>data-v-promotion</code></td>
<td>Include promotional price (<code>true/false</code>)</td>
<td><code>false</code></td>
</tr>
<tr>
<td><strong>include stock</strong></td>
<td align="right"><code>data-v-stock_status</code></td>
<td>Include stock status info (<code>true/false</code>)</td>
<td><code>false</code></td>
</tr>
<tr>
<td><strong>image size</strong></td>
<td align="right"><code>data-v-image_size</code></td>
<td><code>xlarge</code>, <code>large</code>, <code>medium</code>, <code>thumb</code></td>
<td><code>large</code></td>
</tr>
<tr>
<td><strong>image resize</strong></td>
<td align="right"><code>data-v-image_resize</code></td>
<td><code>cs</code> = crop and resize, <code>c</code> = crop, <code>r</code> = resize, <code>s</code> = stretch</td>
<td>Site setting</td>
</tr>
</tbody>
</table>
<hr />
<h3>Component Properties</h3>
<p>Each product returned by the component is wrapped in an element marked with <strong><code>data-v-product</code></strong>. Use the <code>data-v-product-*</code> attributes inside that element to render product fields.</p>
<h4>Core product fields</h4>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th align="right">Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td align="right"><code>data-v-product-name</code></td>
<td>Product title</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td align="right"><code>data-v-product-slug</code></td>
<td>Product slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td align="right"><code>data-v-product-content</code></td>
<td>Full description</td>
</tr>
<tr>
<td><strong>excerpt</strong></td>
<td align="right"><code>data-v-product-excerpt</code></td>
<td>Short description</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td align="right"><code>data-v-product-url</code></td>
<td>Product detail page URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td align="right"><code>data-v-product-image</code></td>
<td>Featured image</td>
</tr>
<tr>
<td><strong>images</strong></td>
<td align="right"><code>data-v-product-images</code></td>
<td>Gallery images</td>
</tr>
<tr>
<td><strong>price</strong></td>
<td align="right"><code>data-v-product-price</code></td>
<td>Price without tax</td>
</tr>
<tr>
<td><strong>price tax</strong></td>
<td align="right"><code>data-v-product-price_tax</code></td>
<td>Price including taxes</td>
</tr>
<tr>
<td><strong>price formatted</strong></td>
<td align="right"><code>data-v-product-price_formatted</code></td>
<td>Formatted price with currency</td>
</tr>
<tr>
<td><strong>price tax formatted</strong></td>
<td align="right"><code>data-v-product-price_tax_formatted</code></td>
<td>Formatted price including taxes with currency</td>
</tr>
<tr>
<td><strong>old price</strong></td>
<td align="right"><code>data-v-product-old_price</code></td>
<td>Price before discount</td>
</tr>
<tr>
<td><strong>old price tax</strong></td>
<td align="right"><code>data-v-product-old_price_tax</code></td>
<td>Price before discount with tax</td>
</tr>
<tr>
<td><strong>old price tax formatted</strong></td>
<td align="right"><code>data-v-product-old_price_tax</code></td>
<td>Price before discount with taxes and currency</td>
</tr>
<tr>
<td><strong>stock quantity</strong></td>
<td align="right"><code>data-v-product-stock_quantity</code></td>
<td>Units in stock</td>
</tr>
<tr>
<td><strong>stock status</strong></td>
<td align="right"><code>data-v-product-stock_status_id</code></td>
<td>Stock status id/name</td>
</tr>
<tr>
<td><strong>product id</strong></td>
<td align="right"><code>data-v-product-product_id</code></td>
<td>Internal product id</td>
</tr>
<tr>
<td><strong>product variant id</strong></td>
<td align="right"><code>data-v-product-product_variant_id</code></td>
<td>Active variant id</td>
</tr>
<tr>
<td><strong>has variants</strong></td>
<td align="right"><code>data-v-product-has_variants</code></td>
<td><code>true/false</code></td>
</tr>
<tr>
<td><strong>add to cart url</strong></td>
<td align="right"><code>data-v-product-add_cart_url</code></td>
<td>URL to add product to cart</td>
</tr>
<tr>
<td><strong>buy url</strong></td>
<td align="right"><code>data-v-product-buy_url</code></td>
<td>Direct buy URL</td>
</tr>
<tr>
<td><strong>manufacturer</strong></td>
<td align="right"><code>data-v-product-manufacturer_name</code></td>
<td>Manufacturer name</td>
</tr>
<tr>
<td><strong>vendor</strong></td>
<td align="right"><code>data-v-product-vendor_name</code></td>
<td>Vendor name</td>
</tr>
<tr>
<td><strong>created at</strong></td>
<td align="right"><code>data-v-product-created_at</code></td>
<td>Creation timestamp</td>
</tr>
<tr>
<td><strong>updated at</strong></td>
<td align="right"><code>data-v-product-updated_at</code></td>
<td>Last update timestamp</td>
</tr>
<tr>
<td><strong>pubDate at</strong></td>
<td align="right"><code>data-v-product-pubDate</code></td>
<td>Publish date in RFC2822 format</td>
</tr>
<tr>
<td><strong>modDate at</strong></td>
<td align="right"><code>data-v-product-modDate</code></td>
<td>Last update in RFC2822 format</td>
</tr>
</tbody>
</table>
<h4>Additional available properties</h4>
<p>The component exposes many more fields for advanced templates.
Common additional fields include: <code>sku</code>; <code>model</code>; <code>mpn</code>; <code>barcode</code>; <code>origin_country</code>; <code>weight</code>, <code>weight_type_id</code>; <code>length</code>, <code>width</code>, <code>height</code>, <code>length_type_id</code>; <code>tax_type_id</code>; <code>points</code>; <code>promotion_*</code> fields; <code>min_price</code> / <code>max_price</code> for variants; <code>reviews</code> and <code>rating</code>; <code>product_related</code>; <code>product_option</code> and <code>product_option_value</code>; <code>product_to_site</code> (site visibility); <code>price_formatted</code> variants for tax/no-tax; <code>pubDate</code> and <code>modDate</code>. Use these when you need detailed product data or variant-aware pricing.</p>
<hr />
<h3>Example Usage</h3>
<pre><code class="language-html">&lt;div data-v-component-product
     data-v-slug=&quot;product-19&quot;
     data-v-limit=&quot;1&quot;&gt;

  &lt;div class=&quot;product-card&quot; data-v-product&gt;
    &lt;a href=&quot;&quot; data-v-product-url&gt;
      &lt;img src=&quot;/placeholder.jpg&quot; data-v-product-image alt=&quot;Product Image&quot;&gt;
      &lt;h3 data-v-product-name&gt;&lt;/h3&gt;
    &lt;/a&gt;

    &lt;p data-v-product-excerpt&gt;&lt;/p&gt;

    &lt;div class=&quot;price&quot;&gt;
      &lt;span class=&quot;price-current&quot; data-v-product-price_formatted&gt;&lt;/span&gt;
      &lt;span class=&quot;price-old&quot; data-v-product-old_price_formatted data-v-if=&quot;product.old_price&quot;&gt;&lt;/span&gt;
    &lt;/div&gt;

    &lt;div class=&quot;actions&quot;&gt;
      &lt;a class=&quot;btn btn-outline&quot; data-v-product-add_cart_url&gt; Add to cart &lt;/a&gt;
      &lt;a class=&quot;btn btn-primary&quot; data-v-product-buy_url&gt; Buy now &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div data-v-if-not=&quot;products&quot;&gt;
    &lt;p&gt;No products match your criteria.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<hr />
<h3>Notes and Best Practices</h3>
<ul>
<li><strong>Load by page context</strong>: On a product detail page you can omit <code>data-v-product_id</code> and <code>data-v-slug</code>; the component will detect the product from the page URL.</li>
<li><strong>Variants and pricing</strong>: If your store uses variants, set <code>data-v-product_variant_id</code> or enable <code>data-v-variant</code> to surface variant-specific price and option fields.</li>
<li><strong>Formatting</strong>: Use the formatted price attributes (<code>*_formatted</code>) to display currency symbol and decimals consistently.</li>
<li><strong>Multisite and multilingual</strong>: Combine <code>data-v-site_id</code> and <code>data-v-language_id</code> to render site‑specific or language‑specific product content.</li>
</ul>

<p>The <strong>Product</strong> component displays a single product on any page or template.</p>
<hr />
<h2>Component Options</h2>
<p>Each option can be added as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>product_id</strong> - Id of the product to display. Default: url (take id from the page get parameter).</li>
<li><strong>slug</strong> - Slug of the product to display. Default: url (take slug from the page get parameter).</li>
<li><strong>limit</strong> - Number of products to display. Default: <code>4</code>.</li>
<li><strong>page</strong> - Page number for pagination. Total pages = total products ÷ limit.</li>
<li><strong>language_id</strong> - Language ID for product name and content. Default: current language.</li>
<li><strong>site_id</strong> - Site ID to load products from. Default: current site.</li>
<li><strong>type</strong> - Product type. Default: <code>product</code>. Useful for custom product types.</li>
<li><strong>status</strong> - <code>1</code> = enabled, <code>0</code> = disabled, default 1.
'user_group_id'       =&gt; null, // user group id to use to calculate promotional price
'product_variant_id'  =&gt; null, // product variant id to display variant as default, for price and product options
'variant'             =&gt; null, //[true, false] include variants
'variant_price'       =&gt; null, //[true, false] include variants prices
'promotion'           =&gt; null, //[true, false] include promotional price
'points'              =&gt; null, //[true, false] include points
'stock_status'        =&gt; null, //[true, false] include stock status info
'weight_type'         =&gt; null, //[true, false] include weight type info
'length_type'         =&gt; null, //[true, false] include length type info
'rating'              =&gt; null, //[true, false] include rating average
'reviews'             =&gt; null, //[true, false] include reviews count
'image_size'          =&gt; 'large',    //options: xlarge, large, medium, thumb - if null site settings is used
'image_resize'        =&gt; null,    //options: cs = Crop &amp; resize, c = crop, r = resize, s = stretch - if null site settings is used</li>
</ul>
<hr />
<h2>Component Properties</h2>
<p>Inside the component, the following repeatable product properties are available. Each product is wrapped in an element marked with <code>data-v-product</code>.</p>
<ul>
<li><strong>name</strong> - <code>data-v-product-name</code> - Product name.</li>
<li><strong>content</strong> - <code>data-v-product-content</code> - Product description or content.</li>
<li><strong>price</strong> - <code>data-v-product-price</code> - Product price.</li>
<li><strong>image</strong> - <code>data-v-product-image</code> - Main product image.</li>
<li><strong>images</strong> - <code>data-v-product-images</code> - Product gallery images.</li>
<li><strong>url</strong> - <code>data-v-product-url</code> - Product detail page URL.</li>
<li><strong>product_id</strong> -</li>
<li><strong>language_id</strong> -</li>
<li><strong>name</strong> -
slug
content
excerpt
meta_title
meta_description
meta_keywords
admin_id - id of admin user/author
model
sku
upc
ean
jan
isbn
mpn
barcode
hs_code
origin_country
mid_code
location
stock_quantity - the number of products available in stock
stock_status_id  - stock status id, available, sold out, in one week etc
image - featured product image
manufacturer_id
vendor_id
requires_shipping - if physical product, needs shipping, for digital products should be set to false
old_price - price before discount, if set should be bigger then current price and displayed with a strike out
price - price without tax
points - number points to buy with points
tax_type_id
material
weight
weight_type_id
length
width
height
length_type_id
date_available
type - custom product type, default product
template - if product has a custom template to display the page
views - number of views, used of analytics
subtract_stock - if stock is substracted after a product is bought
minimum_quantity - minimum quantity to allow adding to cart
subscription_onetime - if product has subscriptions and the product can be bought as regular one time without subscription
status - 1 enabled, 0 disabled
sort_order
created_at
updated_at
manufacturer_slug
manufacturer_name
vendor_slug
vendor_name
stock_status_name
product_content - content in all languages for multi language stores
product_image - product images gallery
product_related - related products
product_variant - product variants
product_subscription
product_attribute
product_to_digital_asset
product_discount
product_promotion
product_points
product_option
product_option_value
option_value_content
product_to_site - list of site id's where the product is enabled/visible
images - list of image galelry
add_cart_url
buy_url
add_wishlist_url
add_compare_url
manufacturer_url
vendor_url
product_variant_id
price_tax  - price with tax
price_formatted -  price without tax formatted with currency sign and decimals
price_tax_formatted - price with tax formatted with currency sign and decimals
price_price_currency
promotion_tax
promotion_formatted
promotion_tax_formatted
promotion_price_currency
old_price_tax
old_price_formatted
old_price_tax_formatted
old_price_price_currency
min_price - if product has variants min price is the lowest price among variants
min_price_tax - min price with tax
min_price_formatted  - min price with tax formatted with currency sign and decimals
min_price_tax_formatted
min_price_price_currency
max_price - - if product has variants max price is the biggest price among variants
max_price_tax
max_price_formatted
max_price_tax_formatted
max_price_price_currency
has_variants
pubDate - publish date in RFC2822 format
modDate - modification date in RFC2822 format</li>
</ul>
<p>These properties repeat for each product returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;div data-v-component-product
     data-v-slug=&quot;product-19&quot; 
&gt;

    &lt;div class=&quot;product-card&quot;&gt;
        &lt;img src=&quot;/placeholder.jpg&quot; data-v-product-image alt=&quot;Product Image&quot;&gt;
        
        &lt;h3 data-v-product-name&gt;Product Name Placeholder&lt;/h3&gt;
        &lt;p data-v-product-content&gt;Short description goes here...&lt;/p&gt;
        
        &lt;span class=&quot;price&quot; data-v-product-price_tax_formatted&gt;$0.00&lt;/span&gt;
        
        &lt;a href=&quot;#&quot; data-v-product-url class=&quot;button&quot;&gt;View Product&lt;/a&gt;
    &lt;/div&gt;
    
    &lt;div data-v-if-not=&quot;products&quot;&gt;
        &lt;p&gt;No products match your criteria.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="74">
			<title data-v-post-name="name">Component user</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-user</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The user component displays information about an useristrator user. If no user_id or username is provided, the component automatically shows the currently logged‑in user user. This makes it useful f]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>user</strong> component displays information about an useristrator user.
If no <code>user_id</code> or <code>username</code> is provided, the component automatically shows the currently logged‑in user user.
This makes it useful for author profile pages, dashboards, or any template where user details are needed.</p>
<hr />
<h2>Component Options</h2>
<p>Add any option as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>user_id</strong> - Loads the user user with this ID. If set to <code>url</code>, the component will read the <code>user_id</code> from the URL query string. This is useful for author profile pages where the user ID is dynamic.</li>
<li><strong>username</strong> - Loads the user user with this username. If set to <code>url</code>, the component will read the <code>username</code> from the URL query string.</li>
</ul>
<p>Only one of these options is required. If both are omitted, the component displays the currently authenticated user user.</p>
<hr />
<h2>Component Properties</h2>
<p>The following properties are available inside the component. Each property can be used with its corresponding <code>data-v-user-*</code> attribute.</p>
<ul>
<li><strong>first_name</strong> - <code>data-v-user-first_name</code> - Admin’s first name.</li>
<li><strong>last_name</strong> - <code>data-v-user-last_name</code> - Admin’s last name.</li>
<li><strong>avatar_url</strong> - <code>data-v-user-avatar_url</code> - URL of the user’s profile avatar.</li>
<li><strong>cover_url</strong> - <code>data-v-user-cover_url</code> - URL of the user’s cover/background image.</li>
<li><strong>url</strong> - <code>data-v-user-url</code> - Link to the user’s public profile page.</li>
<li><strong>username</strong> - <code>data-v-user-username</code> - Admin’s username.</li>
<li><strong>display_name</strong> - <code>data-v-user-display_name</code> - Public display name.</li>
<li><strong>website</strong> - <code>data-v-user-website</code> - Personal or professional website.</li>
<li><strong>email</strong> - <code>data-v-user-email</code> - Internal email used for login and notifications.</li>
<li><strong>public_email</strong> - <code>data-v-user-public_email</code> - Publicly visible email address.</li>
<li><strong>bio</strong> - <code>data-v-user-bio</code> - Short biography or description.</li>
<li><strong>created_at</strong> - <code>data-v-user-created_at</code> - Account creation timestamp.</li>
<li><strong>updated_at</strong> - <code>data-v-user-updated_at</code> - Last update timestamp.</li>
<li><strong>role_id</strong> - <code>data-v-user-role_id</code> - Role ID assigned to the user.</li>
<li><strong>role</strong> - <code>data-v-user-role</code> - Role name (e.g., Administrator, Editor).</li>
<li><strong>last_ip</strong> - <code>data-v-user-last_ip</code> - Last login IP address.</li>
<li><strong>phone_number</strong> - <code>data-v-user-phone_number</code> - Public phone number (if provided).</li>
</ul>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;div data-v-component-user data-v-user_id=&quot;url&quot; class=&quot;profile&quot;&gt;

	&lt;div data-v-if=&quot;user&quot;&gt;

		&lt;div class=&quot;profile-header&quot;&gt;
			&lt;div class=&quot;cover&quot;&gt;
				&lt;img src=&quot;&quot; data-v-user-cover_url&gt;
			&lt;/div&gt;

			&lt;div class=&quot;avatar&quot;&gt;
				&lt;img data-v-user-avatar_url class=&quot;rounded-circle avatar&quot; alt=&quot;Profile Picture&quot;&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;div class=&quot;px-3 m-3 me-5 d-flex justify-content-between&quot;&gt;
			&lt;div&gt;
				&lt;h1 class=&quot;h3 m-0&quot; data-v-user-display_name&gt;User&lt;/h1&gt;
			&lt;/div&gt;

			&lt;div class=&quot;social-links d-inline-block&quot;&gt;
				&lt;!-- Optional social links --&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;div class=&quot;px-3 m-3 me-5 d-flex&quot;&gt;

			&lt;div&gt;
				&lt;div class=&quot;text-muted&quot;&gt;@&lt;span data-v-user-username&gt;username&lt;/span&gt;&lt;/div&gt;

				&lt;div&gt;
					&lt;a class=&quot;d-block&quot; data-v-user-website href=&quot;#&quot;&gt;
						&lt;span data-v-user-website&gt;example.com&lt;/span&gt;
					&lt;/a&gt;

					&lt;a class=&quot;d-block text-body small&quot; href=&quot;#&quot;&gt;
						&lt;span data-v-user-public_email&gt;user@vvveb.com&lt;/span&gt;
					&lt;/a&gt;

					&lt;a class=&quot;d-block text-body small&quot; href=&quot;#&quot;&gt;
						&lt;span data-v-user-phone_number&gt;123456&lt;/span&gt;
					&lt;/a&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&quot;ms-5&quot;&gt;
				&lt;div data-v-user-bio&gt;My bio&lt;/div&gt;
			&lt;/div&gt;

		&lt;/div&gt;

	&lt;/div&gt;

&lt;/div&gt;
</code></pre>
<p>This example loads the user profile based on the <code>user_id</code> found in the URL. All user details are displayed using the component’s data attributes.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="75">
			<title data-v-post-name="name">Component cart</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-cart</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Cart Component displays the contents of the user’s shopping cart, including products, applied coupons, totals, taxes, and the grand total. It can be used on cart pages, mini‑cart dropdowns, si]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Cart Component</strong> displays the contents of the user’s shopping cart, including products, applied coupons, totals, taxes, and the grand total.<br />
It can be used on cart pages, mini‑cart dropdowns, sidebars, or checkout summaries.</p>
<p>To activate it, add:</p>
<pre><code>data-v-component-cart
</code></pre>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Add options as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>cart_id</strong></td>
<td><code>data-v-cart_id</code></td>
<td>Load a specific cart by ID, it can also be an encrypted cart id. If omitted, the cart is loaded from the user session or created automatically.</td>
<td>Auto‑detect</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for product names and descriptions</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-site_id</code></td>
<td>Site ID for loading store settings (currency, locale, taxes)</td>
<td>Current site</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>The component exposes cart‑level properties and repeatable lists for products, totals, and coupons.</p>
<h3><strong>Cart Summary Properties</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>total_items</strong></td>
<td><code>data-v-cart-total_items</code></td>
<td>Number of products in the cart</td>
</tr>
<tr>
<td><strong>total</strong></td>
<td><code>data-v-cart-total</code></td>
<td>Grand total (numeric)</td>
</tr>
<tr>
<td><strong>total_formatted</strong></td>
<td><code>data-v-cart-total_formatted</code></td>
<td>Grand total formatted with currency</td>
</tr>
<tr>
<td><strong>total_weight</strong></td>
<td><code>data-v-cart-total_weight</code></td>
<td>Total weight of all products</td>
</tr>
<tr>
<td><strong>cart_id</strong></td>
<td><code>data-v-cart-cart_id</code></td>
<td>Cart ID</td>
</tr>
<tr>
<td><strong>encrypted_cart_id</strong></td>
<td><code>data-v-cart-encrypted_cart_id</code></td>
<td>Encrypted ID for restoring carts via cookies</td>
</tr>
<tr>
<td><strong>weight_unit</strong></td>
<td><code>data-v-cart-weight_unit</code></td>
<td>Weight unit (e.g., kg)</td>
</tr>
<tr>
<td><strong>length_unit</strong></td>
<td><code>data-v-cart-length_unit</code></td>
<td>Length unit (e.g., cm, m)</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Products List</strong></h2>
<p>Each product is wrapped in an element marked with:</p>
<pre><code>data-v-cart-product
</code></pre>
<p>You can use any of the following attributes inside it:</p>
<h3><strong>Product Properties</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-cart-product-name</code></td>
<td>Product name</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-cart-product-slug</code></td>
<td>Product slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-cart-product-content</code></td>
<td>Full description</td>
</tr>
<tr>
<td><strong>excerpt</strong></td>
<td><code>data-v-cart-product-excerpt</code></td>
<td>Short description</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-cart-product-url</code></td>
<td>Product detail page URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td><code>data-v-cart-product-image</code></td>
<td>Featured image</td>
</tr>
<tr>
<td><strong>images</strong></td>
<td><code>data-v-cart-product-images</code></td>
<td>Gallery images</td>
</tr>
<tr>
<td><strong>quantity</strong></td>
<td><code>data-v-cart-product-quantity</code></td>
<td>Quantity in cart</td>
</tr>
<tr>
<td><strong>price</strong></td>
<td><code>data-v-cart-product-price</code></td>
<td>Price without tax</td>
</tr>
<tr>
<td><strong>price_tax</strong></td>
<td><code>data-v-cart-product-price_tax</code></td>
<td>Price including tax</td>
</tr>
<tr>
<td><strong>price_formatted</strong></td>
<td><code>data-v-cart-product-price_formatted</code></td>
<td>Price formatted with currency</td>
</tr>
<tr>
<td><strong>price_tax_formatted</strong></td>
<td><code>data-v-cart-product-price_tax_formatted</code></td>
<td>Price including tax, formatted</td>
</tr>
<tr>
<td><strong>old_price</strong></td>
<td><code>data-v-cart-product-old_price</code></td>
<td>Price before discount</td>
</tr>
<tr>
<td><strong>old_price_tax</strong></td>
<td><code>data-v-cart-product-old_price_tax</code></td>
<td>Old price including tax</td>
</tr>
<tr>
<td><strong>old_price_tax_formatted</strong></td>
<td><code>data-v-cart-product-old_price_tax_formatted</code></td>
<td>Old price formatted</td>
</tr>
<tr>
<td><strong>stock_quantity</strong></td>
<td><code>data-v-cart-product-stock_quantity</code></td>
<td>Units in stock</td>
</tr>
<tr>
<td><strong>stock_status</strong></td>
<td><code>data-v-cart-product-stock_status_id</code></td>
<td>Stock status</td>
</tr>
<tr>
<td><strong>product_id</strong></td>
<td><code>data-v-cart-product-product_id</code></td>
<td>Product ID</td>
</tr>
<tr>
<td><strong>product_variant_id</strong></td>
<td><code>data-v-cart-product-product_variant_id</code></td>
<td>Variant ID</td>
</tr>
<tr>
<td><strong>has_variants</strong></td>
<td><code>data-v-cart-product-has_variants</code></td>
<td>Whether product has variants</td>
</tr>
<tr>
<td><strong>add_cart_url</strong></td>
<td><code>data-v-cart-product-add_cart_url</code></td>
<td>Add‑to‑cart URL</td>
</tr>
<tr>
<td><strong>buy_url</strong></td>
<td><code>data-v-cart-product-buy_url</code></td>
<td>Direct buy URL</td>
</tr>
<tr>
<td><strong>remove_url</strong></td>
<td><code>data-v-cart-product-remove_url</code></td>
<td>Remove from cart URL</td>
</tr>
<tr>
<td><strong>manufacturer_name</strong></td>
<td><code>data-v-cart-product-manufacturer_name</code></td>
<td>Manufacturer</td>
</tr>
<tr>
<td><strong>vendor_name</strong></td>
<td><code>data-v-cart-product-vendor_name</code></td>
<td>Vendor</td>
</tr>
<tr>
<td><strong>subscription_name</strong></td>
<td><code>data-v-cart-product-subscription_name</code></td>
<td>Subscription plan name</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-cart-product-created_at</code></td>
<td>Creation date</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-cart-product-updated_at</code></td>
<td>Last update</td>
</tr>
<tr>
<td><strong>pubDate</strong></td>
<td><code>data-v-cart-product-pubDate</code></td>
<td>Publish date (RSS format)</td>
</tr>
<tr>
<td><strong>modDate</strong></td>
<td><code>data-v-cart-product-modDate</code></td>
<td>Modification date (RSS format)</td>
</tr>
</tbody>
</table>
<p>Product options, variants, and subscription details are also available as nested repeatables.</p>
<hr />
<h2><strong>Totals List</strong></h2>
<p>Each total row is wrapped in:</p>
<pre><code>data-v-cart-total
</code></pre>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>namespace</strong></td>
<td><code>data-v-total-namespace</code></td>
<td>Group: <code>tax</code>, <code>coupon</code>, <code>payment</code>, <code>shipping</code>, <code>total</code>, etc.</td>
</tr>
<tr>
<td><strong>key</strong></td>
<td><code>data-v-total-key</code></td>
<td>Unique key (e.g., <code>tax.1</code>, <code>coupon.3</code>, <code>sub_total</code>)</td>
</tr>
<tr>
<td><strong>title</strong></td>
<td><code>data-v-cart-total-title</code></td>
<td>Label shown to the user</td>
</tr>
<tr>
<td><strong>value</strong></td>
<td><code>data-v-cart-total-value</code></td>
<td>Numeric value</td>
</tr>
<tr>
<td><strong>value_formatted</strong></td>
<td><code>data-v-cart-total-value_formatted</code></td>
<td>Value formatted with currency</td>
</tr>
<tr>
<td><strong>text</strong></td>
<td><code>data-v-cart-total-text</code></td>
<td>Optional explanatory text</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Coupons List</strong></h2>
<p>Each coupon is wrapped in:</p>
<pre><code>data-v-cart-coupon
</code></pre>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>coupon_id</strong></td>
<td><code>data-v-cart-coupon-coupon_id</code></td>
<td>Coupon ID</td>
</tr>
<tr>
<td><strong>code</strong></td>
<td><code>data-v-cart-coupon-code</code></td>
<td>Coupon code entered by user</td>
</tr>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-cart-coupon-name</code></td>
<td>Coupon name</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>data-v-cart-coupon-type</code></td>
<td><code>P</code> = percentage, <code>F</code> = fixed amount</td>
</tr>
<tr>
<td><strong>value</strong></td>
<td><code>data-v-cart-coupon-value</code></td>
<td>Discount value</td>
</tr>
<tr>
<td><strong>free_shipping</strong></td>
<td><code>data-v-cart-coupon-free_shipping</code></td>
<td><code>1</code> = free shipping</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-cart-coupon-status</code></td>
<td><code>1</code> = active</td>
</tr>
<tr>
<td><strong>from_date</strong></td>
<td><code>data-v-cart-coupon-from_date</code></td>
<td>Valid from</td>
</tr>
<tr>
<td><strong>to_date</strong></td>
<td><code>data-v-cart-coupon-to_date</code></td>
<td>Valid until</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-cart-coupon-created_at</code></td>
<td>Creation date</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-cart-coupon-updated_at</code></td>
<td>Last update</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;table class=&quot;products-table&quot;&gt;
	&lt;tbody&gt;

		&lt;tr data-v-cart-product&gt;
			&lt;td&gt;
				&lt;a data-v-cart-product-url&gt;
					&lt;img data-v-cart-product-image width=&quot;50&quot; alt=&quot;Product name&quot;&gt;
				&lt;/a&gt;
			&lt;/td&gt;

			&lt;td&gt;
				&lt;a data-v-cart-product-url&gt;
					&lt;span data-v-cart-product-name&gt;&lt;/span&gt;
				&lt;/a&gt;

				&lt;span data-v-cart-product-quantity&gt;&lt;/span&gt; × 
				&lt;span data-v-cart-product-price_tax_formatted&gt;&lt;/span&gt;

				&lt;div data-v-if=&quot;product.option&quot;&gt;
					&lt;div data-v-product-option&gt;
						&lt;span data-v-product-option-option&gt;&lt;/span&gt;:
						&lt;span data-v-product-option-name&gt;&lt;/span&gt;
						&lt;span data-v-if=&quot;value.price &gt; 0&quot;&gt;
							(&lt;span data-v-product-option-price&gt;&lt;/span&gt;)
						&lt;/span&gt;
					&lt;/div&gt;
				&lt;/div&gt;

				&lt;div data-v-if=&quot;product.subscription&quot;&gt;
					&lt;span&gt;Subscription plan:&lt;/span&gt;
					&lt;span data-v-cart-product-subscription_name&gt;&lt;/span&gt;
				&lt;/div&gt;
			&lt;/td&gt;

			&lt;td&gt;
				&lt;a class=&quot;btn-remove&quot; data-v-vvveb-action=&quot;removeFromCart&quot; data-v-cart-product-remove_url&gt;
					Remove
				&lt;/a&gt;
			&lt;/td&gt;
		&lt;/tr&gt;

		&lt;tr data-v-if-not=&quot;cart.total_items&quot;&gt;
			&lt;td colspan=&quot;100&quot;&gt;Empty cart&lt;/td&gt;
		&lt;/tr&gt;

	&lt;/tbody&gt;
&lt;/table&gt;

&lt;table class=&quot;cart-total&quot;&gt;
  &lt;tfoot&gt;

	  &lt;tr data-v-cart-total&gt;
		 &lt;td colspan=&quot;5&quot;&gt;
			&lt;small data-v-cart-total-title&gt;&lt;/small&gt;:
		 &lt;/td&gt;
		 &lt;td&gt;
			&lt;span data-v-cart-total-text data-v-if=&quot;total.text&quot;&gt;&lt;/span&gt;
			&lt;span data-v-cart-total-value_formatted&gt;&lt;/span&gt;
		 &lt;/td&gt;
	  &lt;/tr&gt;

	  &lt;tr&gt;
		 &lt;td colspan=&quot;5&quot;&gt;Total:&lt;/td&gt;
		 &lt;td data-v-cart-total_formatted&gt;&lt;/td&gt;
	  &lt;/tr&gt;

   &lt;/tfoot&gt;
&lt;/table&gt;
</code></pre>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="76">
			<title data-v-post-name="name">Component reviews</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-reviews</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Product Reviews Component renders a list of reviews for a product. It is typically used on product detail pages, but it can also power recent‑reviews widgets, sidebar lists, or threaded review s]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Product Reviews Component</strong> renders a list of reviews for a product. It is typically used on product detail pages, but it can also power recent‑reviews widgets, sidebar lists, or threaded review sections.</p>
<p>Activate the component by adding:</p>
<pre><code>data-v-component-reviews
</code></pre>
<p>The component supports filtering, sorting, pagination, and nested replies.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<h3><strong>Pagination &amp; Sorting</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>0</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Number of reviews to display</td>
<td><code>4</code></td>
</tr>
<tr>
<td><strong>page</strong></td>
<td><code>data-v-page</code></td>
<td>Page number for pagination</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>order</strong></td>
<td><code>data-v-order</code></td>
<td>Sort field (<code>review_id</code>, <code>user_id</code>, <code>created_at</code>, <code>updated_at</code>)</td>
<td><code>created_at</code></td>
</tr>
<tr>
<td><strong>direction</strong></td>
<td><code>data-v-direction</code></td>
<td>Sort direction (<code>asc</code>, <code>desc</code>)</td>
<td><code>desc</code></td>
</tr>
<tr>
<td><strong>image size</strong></td>
<td><code>data-v-image_size</code></td>
<td><code>xlarge</code>, <code>large</code>, <code>medium</code>, <code>thumb</code></td>
<td><code>thumb</code></td>
</tr>
</tbody>
</table>
<h3><strong>Filtering</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-status</code></td>
<td>Review status: <code>1</code> = published, <code>0</code> = pending, <code>2</code> = spam, <code>3</code> = trash</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>product_id</strong></td>
<td><code>data-v-product_id</code></td>
<td>Filter by product ID</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-slug</code></td>
<td>Filter by product slug</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-user_id</code></td>
<td>Filter by user ID</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<h3><strong>Additional Options</strong></h3>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for review content and product title</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>product_title</strong></td>
<td><code>data-v-product_title</code></td>
<td>Include product title (useful for recent‑reviews widgets)</td>
<td><code>false</code></td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>Each review is wrapped in:</p>
<pre><code>data-v-review
</code></pre>
<p>The following fields are available inside each review element.</p>
<h3><strong>Author Information</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>username</strong></td>
<td><code>data-v-review-username</code></td>
<td>Username of the reviewer</td>
</tr>
<tr>
<td><strong>email</strong></td>
<td><code>data-v-review-email</code></td>
<td>Email address</td>
</tr>
<tr>
<td><strong>first_name</strong></td>
<td><code>data-v-review-first_name</code></td>
<td>First name</td>
</tr>
<tr>
<td><strong>last_name</strong></td>
<td><code>data-v-review-last_name</code></td>
<td>Last name</td>
</tr>
<tr>
<td><strong>display_name</strong></td>
<td><code>data-v-review-display_name</code></td>
<td>Display name</td>
</tr>
<tr>
<td><strong>author</strong></td>
<td><code>data-v-review-author</code></td>
<td>Full author name</td>
</tr>
<tr>
<td><strong>avatar</strong></td>
<td><code>data-v-review-avatar</code></td>
<td>Avatar filename</td>
</tr>
<tr>
<td><strong>avatar_url</strong></td>
<td><code>data-v-review-avatar_url</code></td>
<td>Full avatar URL</td>
</tr>
<tr>
<td><strong>bio</strong></td>
<td><code>data-v-review-bio</code></td>
<td>Author biography</td>
</tr>
<tr>
<td><strong>subscribe</strong></td>
<td><code>data-v-review-subscribe</code></td>
<td>Whether the user subscribed to replies</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Review Metadata</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>review_id</strong></td>
<td><code>data-v-review-review_id</code></td>
<td>Unique review ID</td>
</tr>
<tr>
<td><strong>product_id</strong></td>
<td><code>data-v-review-product_id</code></td>
<td>ID of the product the review belongs to</td>
</tr>
<tr>
<td><strong>user_id</strong></td>
<td><code>data-v-review-user_id</code></td>
<td>ID of the user who producted the review</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-review-url</code></td>
<td>Author’s website URL</td>
</tr>
<tr>
<td><strong>ip</strong></td>
<td><code>data-v-review-ip</code></td>
<td>IP address (if stored)</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-review-status</code></td>
<td>Review status</td>
</tr>
<tr>
<td><strong>rating</strong></td>
<td><code>data-v-review-rating</code></td>
<td>Rating 1 to 5</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>data-v-review-type</code></td>
<td>Review type (empty for standard reviews)</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td><code>data-v-review-parent_id</code></td>
<td>Parent review ID (for threaded replies)</td>
</tr>
<tr>
<td><strong>level</strong></td>
<td><code>data-v-review-level</code></td>
<td>Nesting level for threaded reviews</td>
</tr>
<tr>
<td><strong>created_at</strong></td>
<td><code>data-v-review-created_at</code></td>
<td>Creation timestamp</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-review-updated_at</code></td>
<td>Last update timestamp</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Review Content</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-review-content</code></td>
<td>Review text</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Product Information (Optional)</strong></h3>
<p>Displayed only when <code>data-v-product_title=&quot;true&quot;</code> is used.</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-review-name</code></td>
<td>Title of the product the review belongs to</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-review-slug</code></td>
<td>Slug of the product the review belongs to</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-component-reviews data-v-product_id=&quot;url&quot;&gt;

  &lt;ol data-v-if=&quot;count &gt; 0&quot;&gt;

    &lt;li data-v-review&gt;

      &lt;div class=&quot;review-wrap&quot;&gt;

        &lt;figure class=&quot;author-avatar me-2&quot;&gt;
          &lt;img data-v-review-avatar_url
               alt=&quot;user&quot;
               width=&quot;60&quot;
               loading=&quot;lazy&quot;
               src=&quot;/media/vvveb.svg&quot; 
               data-v-if=&quot;review.avatar_url&quot;&gt;
        &lt;/figure&gt;

        &lt;div class=&quot;review-author&quot;&gt;

          &lt;a rel=&quot;external nofollow ugc&quot; data-v-if=&quot;review.url&quot;&gt;
            &lt;span data-v-review-author&gt;John Doe&lt;&lt;/span&gt;
          &lt;/a&gt;


	&lt;div class=&quot;review-meta&quot;&gt;
	  &lt;span data-v-review-created_at data-filter-friendly_date&gt;3 year ago&lt;/span&gt;
	&lt;/div&gt;


        &lt;/div&gt;

      &lt;/div&gt;

		&lt;div data-v-review-content&gt;This is an approved review.&lt;/div&gt;

      &lt;div class=&quot;reply&quot;&gt;
        &lt;a href=&quot;#review-form&quot;
           class=&quot;reply-btn&quot;
           data-v-vvveb-action=&quot;replyTo&quot;
           data-review_id
           data-review_author&gt;
          Reply &lt;i class=&quot;la la-reply&quot;&gt;&lt;/i&gt;
        &lt;/a&gt;
      &lt;/div&gt;

    &lt;/li&gt;

  &lt;/ol&gt;

  &lt;div class=&quot;alert&quot; role=&quot;alert&quot; data-v-if-not=&quot;this.default_review_status&quot;&gt;
    &lt;div data-v-notification-text&gt;
      &lt;span&gt;Reviews are closed&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

</code></pre>
<p>This example displays a threaded review list with avatars, author names, timestamps, content, and reply actions.</p>
<h1><strong>Product Review Form Component</strong></h1>
<p>The <strong>Review Form</strong> handles review submission on product pages.
It works together with the <strong>Product Reviews Component</strong>, allowing users to submit new reviews or reply to existing ones. The form supports logged‑in users, anonymous reviewers (if enabled), CSRF protection, and threaded replies.</p>
<p>To use javascript to product the review without refreshing the page add the following attributes:</p>
<pre><code>data-v-vvveb-action=&quot;addReview&quot;
data-v-vvveb-on=&quot;submit&quot;
</code></pre>
<p>These attributes instruct Vvveb CMS to process the form submission through javascript fetch.</p>
<hr />
<h2><strong>How the Review Form Works</strong></h2>
<p>The form products data to the current page and is intercepted by the Vvveb action handler. The handler:</p>
<ul>
<li>Validates required fields</li>
<li>Checks CSRF token</li>
<li>Determines whether the user is logged in or anonymous</li>
<li>Creates a new review in the database</li>
<li>Assigns the review to the correct product</li>
<li>Handles threaded replies via <code>parent_id</code></li>
<li>Returns success or error notifications</li>
</ul>
<p>If reviews require moderation, the submitted review may be stored with <code>status = 0</code> (pending).</p>
<hr />
<h2><strong>Form Fields</strong></h2>
<p>The form includes a mix of visible and hidden fields. These fields are required for proper review submission.</p>
<h3><strong>Hidden System Fields</strong></h3>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>product_id</strong></td>
<td>Identifies the product the review belongs to</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td>Product slug (used for redirects and validation)</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td>ID of the parent review (0 for top‑level reviews)</td>
</tr>
<tr>
<td><strong>csrf</strong></td>
<td>CSRF token for security</td>
</tr>
<tr>
<td><strong>firstname-empty</strong></td>
<td>Honeypot anti‑spam field (must remain empty)</td>
</tr>
<tr>
<td><strong>subject-empty</strong></td>
<td>Honeypot anti‑spam field</td>
</tr>
<tr>
<td><strong>lastname-empty</strong></td>
<td>Honeypot anti‑spam field</td>
</tr>
</tbody>
</table>
<p>Honeypot fields help block bots without affecting real users.</p>
<hr />
<h3><strong>User Identity Fields</strong></h3>
<p>These fields are shown only when the user is <strong>not logged in</strong>:</p>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>author</strong></td>
<td>Yes</td>
<td>Name of the reviewer</td>
</tr>
<tr>
<td><strong>email</strong></td>
<td>Yes</td>
<td>Email address of the reviewer</td>
</tr>
</tbody>
</table>
<p>When the user is logged in, these fields are omitted because the system already knows the user’s identity.</p>
<hr />
<h3><strong>Review Content</strong></h3>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>content</strong></td>
<td>Yes</td>
<td>The actual review text</td>
</tr>
</tbody>
</table>
<p>This is the main body of the review.</p>
<hr />
<h2><strong>Replying to Reviews</strong></h2>
<p>The reply links in the review list use:</p>
<pre><code>data-v-vvveb-action=&quot;replyTo&quot;
</code></pre>
<p>This action:</p>
<ul>
<li>Scrolls to the review form</li>
<li>Sets the hidden <code>parent_id</code> field to the ID of the review being replied to</li>
<li>Optionally displays the name of the user being replied to</li>
</ul>
<p>This enables threaded/nested reviews.</p>
<hr />
<h2><strong>Anonymous Reviews</strong></h2>
<p>The form includes:</p>
<pre><code>data-v-if=&quot;this.global.user_id || this.anonymous_reviews&quot;
</code></pre>
<p>This means:</p>
<ul>
<li>If the user is logged in → show the form</li>
<li>If the user is not logged in but anonymous reviews are allowed → show the form</li>
<li>Otherwise → hide the form</li>
</ul>
<p>Anonymous review settings are controlled in the site configuration.</p>
<hr />
<h2><strong>Validation &amp; Security</strong></h2>
<p>The review form includes several built‑in protections:</p>
<ul>
<li><strong>CSRF token</strong> (<code>data-v-csrf</code>)</li>
<li><strong>Honeypot fields</strong> (<code>firstname-empty</code>, <code>subject-empty</code>, <code>lastname-empty</code>)</li>
<li><strong>Server‑side validation</strong> of required fields</li>
<li><strong>Status filtering</strong> (pending, spam, trash)</li>
</ul>
<p>If moderation is enabled, reviews may not appear immediately.</p>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;form id=&quot;review-form&quot;
      method=&quot;post&quot;
      action=&quot;&quot;
      data-v-vvveb-action=&quot;addReview&quot;
      data-v-vvveb-on=&quot;submit&quot;
      data-v-if=&quot;this.global.user_id || this.anonymous_reviews&quot;&gt;

  &lt;input type=&quot;hidden&quot; name=&quot;product_id&quot; data-v-product-product_id&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;slug&quot; data-v-product-slug&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;parent_id&quot; value=&quot;0&quot;&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;csrf&quot; data-v-csrf&gt;

  &lt;!-- Honeypot anti-spam fields --&gt;
  &lt;input type=&quot;hidden&quot; name=&quot;firstname-empty&quot;&gt;
  &lt;input type=&quot;text&quot; class=&quot;visually-hidden&quot; name=&quot;lastname-empty&quot; tabindex=&quot;-1&quot;&gt;
  &lt;input type=&quot;text&quot; class=&quot;d-none&quot; name=&quot;subject-empty&quot;&gt;

  &lt;!-- Anonymous user fields --&gt;
  &lt;div data-v-if-not=&quot;this.global.user_id&quot;&gt;
    &lt;div class=&quot;mb-3&quot;&gt;
      &lt;label class=&quot;form-label&quot;&gt;Name&lt;/label&gt;
      &lt;input type=&quot;text&quot; name=&quot;author&quot; class=&quot;form-control&quot; required&gt;
    &lt;/div&gt;

    &lt;div class=&quot;mb-3&quot;&gt;
      &lt;label class=&quot;form-label&quot;&gt;Email address&lt;/label&gt;
      &lt;input type=&quot;email&quot; name=&quot;email&quot; class=&quot;form-control&quot; required&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- Review text --&gt;
  &lt;div class=&quot;mb-3&quot;&gt;
    &lt;textarea name=&quot;content&quot; rows=&quot;5&quot; class=&quot;form-control&quot; placeholder=&quot;Review&quot; required&gt;&lt;/textarea&gt;
  &lt;/div&gt;

  &lt;!-- Submit --&gt;
  &lt;button type=&quot;submit&quot; class=&quot;btn btn-primary btn-submit&quot;&gt;
    &lt;span class=&quot;loading d-none&quot;&gt;
      &lt;span class=&quot;spinner-border spinner-border-sm&quot;&gt;&lt;/span&gt;
      &lt;span&gt;Producting...&lt;/span&gt;
    &lt;/span&gt;

    &lt;span class=&quot;button-text&quot;&gt;
      &lt;span&gt;Product review&lt;/span&gt;
      &lt;i class=&quot;la la-long-arrow-alt-right ms-1&quot;&gt;&lt;/i&gt;
    &lt;/span&gt;
  &lt;/button&gt;

&lt;/form&gt;
</code></pre>
<p>This example includes all required fields, anonymous user handling, CSRF protection, and reply support.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="77">
			<title data-v-post-name="name">Component products</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-products</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Products component displays a list of products on any page or template. It supports filtering, sorting, pagination, and optional image galleries, making it suitable for category pages, featured pr]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Products</strong> component displays a list of products on any page or template. It supports filtering, sorting, pagination, and optional image galleries, making it suitable for category pages, featured product sections, search results, or custom product listings.</p>
<hr />
<h2>Component Options</h2>
<p>Each option can be added as an HTML attribute using the <code>data-v-*</code> syntax.</p>
<ul>
<li><strong>start</strong> - Starting offset for pagination. Default: <code>0</code>.</li>
<li><strong>limit</strong> - Number of products to display. Default: <code>4</code>.</li>
<li><strong>page</strong> - Page number for pagination. Total pages = total products ÷ limit.</li>
<li><strong>language_id</strong> - Language ID for product name and content. Default: current language.</li>
<li><strong>site_id</strong> - Site ID to load products from. Default: current site.</li>
<li><strong>type</strong> - Product type. Default: <code>product</code>. Useful for custom product types.</li>
<li><strong>manufacturer_id</strong> - Filter by manufacturer ID. Default: <code>null</code>.</li>
<li><strong>vendor_id</strong> - Filter by vendor ID. Default: <code>null</code>.</li>
<li><strong>order</strong> - Field used for sorting. Options: <code>product_id</code>, <code>price</code>, <code>date_added</code>, <code>date_modified</code>.</li>
<li><strong>direction</strong> - Sorting direction. Options: <code>asc</code>, <code>desc</code>.</li>
<li><strong>taxonomy_item_id</strong> - Filter by taxonomy (category, collection, etc.).</li>
<li><strong>include_image_gallery</strong> - Include product gallery images. Useful for hover image swap. Default: <code>true</code>.</li>
<li><strong>product_id</strong> - Filter by one or more product IDs. Accepts single value or comma‑separated list (e.g., <code>1,2,3</code>).</li>
<li><strong>search</strong> - Search term to filter products by name or description.</li>
<li><strong>slug</strong> - Filter by product slug. Accepts single value or comma‑separated list (e.g., <code>slug-1,slug-2</code>).</li>
<li><strong>related</strong> - Display products related to a specific product. Value must be the product_id of the reference product.</li>
</ul>
<hr />
<h2>Component Properties</h2>
<p>Inside the component, the following repeatable product properties are available. Each product is wrapped in an element marked with <code>data-v-product</code>.</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th align="right">Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td align="right"><code>data-v-product-name</code></td>
<td>Product title</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td align="right"><code>data-v-product-slug</code></td>
<td>Product slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td align="right"><code>data-v-product-content</code></td>
<td>Full description</td>
</tr>
<tr>
<td><strong>excerpt</strong></td>
<td align="right"><code>data-v-product-excerpt</code></td>
<td>Short description</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td align="right"><code>data-v-product-url</code></td>
<td>Product detail page URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td align="right"><code>data-v-product-image</code></td>
<td>Featured image</td>
</tr>
<tr>
<td><strong>images</strong></td>
<td align="right"><code>data-v-product-images</code></td>
<td>Gallery images</td>
</tr>
<tr>
<td><strong>price</strong></td>
<td align="right"><code>data-v-product-price</code></td>
<td>Price without tax</td>
</tr>
<tr>
<td><strong>price tax</strong></td>
<td align="right"><code>data-v-product-price_tax</code></td>
<td>Price including taxes</td>
</tr>
<tr>
<td><strong>price formatted</strong></td>
<td align="right"><code>data-v-product-price_formatted</code></td>
<td>Formatted price with currency</td>
</tr>
<tr>
<td><strong>price tax formatted</strong></td>
<td align="right"><code>data-v-product-price_tax_formatted</code></td>
<td>Formatted price including taxes with currency</td>
</tr>
<tr>
<td><strong>old price</strong></td>
<td align="right"><code>data-v-product-old_price</code></td>
<td>Price before discount</td>
</tr>
<tr>
<td><strong>old price tax</strong></td>
<td align="right"><code>data-v-product-old_price_tax</code></td>
<td>Price before discount with tax</td>
</tr>
<tr>
<td><strong>old price tax formatted</strong></td>
<td align="right"><code>data-v-product-old_price_tax</code></td>
<td>Price before discount with taxes and currency</td>
</tr>
<tr>
<td><strong>stock quantity</strong></td>
<td align="right"><code>data-v-product-stock_quantity</code></td>
<td>Units in stock</td>
</tr>
<tr>
<td><strong>stock status</strong></td>
<td align="right"><code>data-v-product-stock_status_id</code></td>
<td>Stock status id/name</td>
</tr>
<tr>
<td><strong>product id</strong></td>
<td align="right"><code>data-v-product-product_id</code></td>
<td>Internal product id</td>
</tr>
<tr>
<td><strong>product variant id</strong></td>
<td align="right"><code>data-v-product-product_variant_id</code></td>
<td>Active variant id</td>
</tr>
<tr>
<td><strong>has variants</strong></td>
<td align="right"><code>data-v-product-has_variants</code></td>
<td><code>true/false</code></td>
</tr>
<tr>
<td><strong>add to cart url</strong></td>
<td align="right"><code>data-v-product-add_cart_url</code></td>
<td>URL to add product to cart</td>
</tr>
<tr>
<td><strong>buy url</strong></td>
<td align="right"><code>data-v-product-buy_url</code></td>
<td>Direct buy URL</td>
</tr>
<tr>
<td><strong>manufacturer</strong></td>
<td align="right"><code>data-v-product-manufacturer_name</code></td>
<td>Manufacturer name</td>
</tr>
<tr>
<td><strong>vendor</strong></td>
<td align="right"><code>data-v-product-vendor_name</code></td>
<td>Vendor name</td>
</tr>
<tr>
<td><strong>created at</strong></td>
<td align="right"><code>data-v-product-created_at</code></td>
<td>Creation timestamp</td>
</tr>
<tr>
<td><strong>updated at</strong></td>
<td align="right"><code>data-v-product-updated_at</code></td>
<td>Last update timestamp</td>
</tr>
<tr>
<td><strong>pubDate at</strong></td>
<td align="right"><code>data-v-product-pubDate</code></td>
<td>Publish date in RFC2822 format</td>
</tr>
<tr>
<td><strong>modDate at</strong></td>
<td align="right"><code>data-v-product-modDate</code></td>
<td>Last update in RFC2822 format</td>
</tr>
</tbody>
</table>
<p>These properties repeat for each product returned by the component.</p>
<hr />
<h2>HTML Example</h2>
<pre><code class="language-html">&lt;div data-v-component-products 
     data-v-limit=&quot;10&quot; 
     data-v-page=&quot;2&quot; 
     data-v-order=&quot;price&quot;
     data-v-direction=&quot;asc&quot;
     data-v-include_image_gallery=&quot;false&quot;&gt;

    &lt;div class=&quot;product-card&quot; data-v-product&gt;
        &lt;img src=&quot;/placeholder.jpg&quot; data-v-product-image alt=&quot;Product Image&quot;&gt;
        
        &lt;h3 data-v-product-name&gt;Product Name Placeholder&lt;/h3&gt;
        &lt;p data-v-product-content&gt;Short description goes here...&lt;/p&gt;
        
        &lt;span class=&quot;price&quot; data-v-product-price&gt;$0.00&lt;/span&gt;
        
        &lt;a href=&quot;#&quot; data-v-product-url class=&quot;button&quot;&gt;View Product&lt;/a&gt;
    &lt;/div&gt;
    
    &lt;div data-v-if-not=&quot;products&quot;&gt;
        &lt;p&gt;No products match your criteria.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>This example loads 10 products from page 2, without including the image gallery. Each product is rendered inside the <code>data-v-product</code> block.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="78">
			<title data-v-post-name="name">Component category</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-category</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Category Component displays a single taxonomy item (category or tag) along with its properties, such as name, description, image, and URL. It is typically used on category pages, sidebars, product]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Category Component</strong> displays a single taxonomy item (category or tag) along with its properties, such as name, description, image, and URL.
It is typically used on category pages, sidebars, product filters, or anywhere you need to show details about a specific category.</p>
<p>You can load a category by ID, slug, or automatically from the current page URL.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>All options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>taxonomy_item_id</strong></td>
<td>Category/Taxonomy ID. If not provided, the component automatically detects the ID from the page URL when used on a category page.</td>
<td>URL‑based detection</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td>Category slug. Can be used instead of <code>taxonomy_item_id</code> to load a specific category.</td>
<td>None</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td>Load category content for a specific language.</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td>Load category from a specific site.</td>
<td>Current site</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td>Taxonomy type: <code>categories</code> or <code>tags</code>.</td>
<td><code>categories</code></td>
</tr>
<tr>
<td><strong>post_type</strong></td>
<td>Post type for custom taxonomies (e.g., <code>product</code>, <code>event</code>).</td>
<td><code>post</code></td>
</tr>
</tbody>
</table>
<p>You can combine <code>slug</code>, <code>taxonomy_item_id</code>, and <code>post_type</code> to load exactly the category you want.</p>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>Inside the component, category data is exposed through <code>data-v-cat-*</code> attributes.<br />
These can be used to display category details in your HTML.</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-cat-name</code></td>
<td>Category name</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-cat-slug</code></td>
<td>URL slug</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-cat-content</code></td>
<td>Category description/content</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-cat-url</code></td>
<td>Category URL</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td><code>data-v-cat-image</code></td>
<td>Category image</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td><code>data-v-cat-parent_id</code></td>
<td>Parent category ID (<code>0</code> = top level)</td>
</tr>
<tr>
<td><strong>item_id</strong></td>
<td><code>data-v-cat-item_id</code></td>
<td>Category ID</td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-cat-sort_order</code></td>
<td>Sort order</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-cat-status</code></td>
<td><code>1</code> = enabled, <code>0</code> = disabled</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-cat-language_id</code></td>
<td>Language ID for multilingual content</td>
</tr>
</tbody>
</table>
<p>These properties allow you to build fully custom category layouts.</p>
<hr />
<h2><strong>Example Usage</strong></h2>
<pre><code class="language-html">&lt;div class=&quot;card&quot; 
     data-v-component-category
     data-v-slug=&quot;toys&quot;
     data-v-post_type=&quot;post&quot;&gt;

    &lt;a data-v-cat-url&gt;
        &lt;h3 data-v-cat-name&gt;&lt;/h3&gt;
    &lt;/a&gt;

    &lt;p data-v-cat-content&gt;&lt;/p&gt;

    &lt;img data-v-cat-image src=&quot;demo/img/bg-img/bg-7.webp&quot; alt=&quot;&quot;&gt;
&lt;/div&gt;
</code></pre>
<p>This example loads the category with slug <strong>toys</strong>, displays its name, description, and image, and links to the category page.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="79">
			<title data-v-post-name="name">Component currency</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-currency</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Currency Component displays a list of available currencies and exposes information about the currently selected currency. 
It is commonly used to build currency switchers in navigation bars, heade]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Currency Component</strong> displays a list of available currencies and exposes information about the currently selected currency.</p>
<p>It is commonly used to build currency switchers in navigation bars, headers, footers, or mobile menus.</p>
<p>When a user selects a currency, the component updates the active store currency so product prices are displayed using the selected currency’s value and formatting.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>All options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Maximum number of currencies to display</td>
<td><code>1000</code></td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-status</code></td>
<td><code>1</code> = show only active currencies, <code>0</code> = show all</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>site_only</strong></td>
<td><code>data-v-site_only</code></td>
<td>Show only currencies enabled for the current site</td>
<td><code>true</code></td>
</tr>
<tr>
<td><strong>default</strong></td>
<td><code>data-v-default</code></td>
<td>Preselect a specific currency; if not set, uses site default</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<p>These options allow you to filter, limit, or override which currencies appear in the component.</p>
<hr />
<h2><strong>Component Properties</strong></h2>
<h3><strong>Current Currency Properties</strong></h3>
<p>The currently active currency is exposed through <code>data-v-currency-info-*</code> attributes:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-currency-name</code></td>
<td>Currency name (e.g., <em>US Dollar</em>)</td>
</tr>
<tr>
<td><strong>code</strong></td>
<td><code>data-v-currency-code</code></td>
<td>ISO currency code (e.g., <code>USD</code>)</td>
</tr>
<tr>
<td><strong>value</strong></td>
<td><code>data-v-currency-value</code></td>
<td>Conversion value relative to the base currency (<code>1</code> = base)</td>
</tr>
<tr>
<td><strong>currency_id</strong></td>
<td><code>data-v-currency-currency_id</code></td>
<td>Internal currency ID</td>
</tr>
<tr>
<td><strong>sign_start</strong></td>
<td><code>data-v-currency-sign_start</code></td>
<td>Symbol before the amount (e.g., <code>$</code>)</td>
</tr>
<tr>
<td><strong>sign_end</strong></td>
<td><code>data-v-currency-sign_end</code></td>
<td>Symbol after the amount (e.g., <code>€</code>)</td>
</tr>
<tr>
<td><strong>decimal_place</strong></td>
<td><code>data-v-currency-decimal_place</code></td>
<td>Number of decimals (e.g., <code>2</code>)</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-currency-status</code></td>
<td>Currency status (<code>1</code> = active)</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-currency-updated_at</code></td>
<td>Last update timestamp (useful when values are synced via API)</td>
</tr>
</tbody>
</table>
<p>These attributes are ideal for showing the currently selected currency in a dropdown or header.</p>
<hr />
<h3><strong>Available Currencies (Repeatable)</strong></h3>
<p>Currencies are listed inside a <code>data-v-currency</code> container.<br />
Each currency exposes the following properties:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-currency-name</code></td>
<td>Currency name</td>
</tr>
<tr>
<td><strong>code</strong></td>
<td><code>data-v-currency-code</code></td>
<td>ISO currency code</td>
</tr>
<tr>
<td><strong>value</strong></td>
<td><code>data-v-currency-value</code></td>
<td>Conversion value relative to base currency</td>
</tr>
<tr>
<td><strong>currency_id</strong></td>
<td><code>data-v-currency-currency_id</code></td>
<td>Internal ID</td>
</tr>
<tr>
<td><strong>sign_start</strong></td>
<td><code>data-v-currency-sign_start</code></td>
<td>Symbol before the amount</td>
</tr>
<tr>
<td><strong>sign_end</strong></td>
<td><code>data-v-currency-sign_end</code></td>
<td>Symbol after the amount</td>
</tr>
<tr>
<td><strong>decimal_place</strong></td>
<td><code>data-v-currency-decimal_place</code></td>
<td>Decimal precision</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-currency-status</code></td>
<td>Active/inactive</td>
</tr>
<tr>
<td><strong>updated_at</strong></td>
<td><code>data-v-currency-updated_at</code></td>
<td>Last update timestamp</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>Note:</strong><br />
Unlike the Language Component, the Currency Component does <strong>not</strong> generate translated URLs.<br />
Currency switching affects <strong>price display only</strong>, not page routing.</p>
</blockquote>
<hr />
<h2><strong>Example Usage</strong></h2>
<pre><code class="language-html">&lt;div class=&quot;dropdown&quot; data-v-component-currency&gt;
	&lt;form method=&quot;post&quot; enctype=&quot;multipart/form-data&quot; id=&quot;form-currency&quot;&gt;

		&lt;a class=&quot;dropdown-toggle&quot; 
		   data-bs-toggle=&quot;dropdown&quot; 
		   role=&quot;button&quot; 
		   title=&quot;Currency&quot;&gt;

			&lt;span data-v-currency-info-name&gt;&lt;/span&gt;
		&lt;/a&gt;

		&lt;div class=&quot;dropdown-menu&quot;&gt;

			&lt;div data-v-currency&gt;
			  &lt;button class=&quot;dropdown-item&quot; 
			          type=&quot;submit&quot; 
			          name=&quot;currency&quot; 
			          data-v-currency-code&gt;

				&lt;span class=&quot;small text-muted&quot; data-v-currency-sign_start&gt;&lt;/span&gt;
				&lt;span class=&quot;small text-muted&quot; data-v-currency-sign_end&gt;&lt;/span&gt;
				&lt;span data-v-currency-name&gt;&lt;/span&gt;
			  &lt;/button&gt;
			&lt;/div&gt;

		&lt;/div&gt;
	&lt;/form&gt;
&lt;/div&gt;
</code></pre>
<p>This example creates a fully functional currency selector that:</p>
<ul>
<li>Displays the current currency</li>
<li>Lists all available currencies</li>
<li>Submits the selected currency code</li>
<li>Updates the store’s active currency for price display</li>
</ul>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="80">
			<title data-v-post-name="name">Component language</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-language</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Language Component displays a list of available languages and provides access to the currently selected language. 
It is typically used for language switchers in navigation bars, headers, or foote]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Language Component</strong> displays a list of available languages and provides access to the currently selected language.</p>
<p>It is typically used for language switchers in navigation bars, headers, or footers.</p>
<p>The component automatically generates URLs for the translated version of the current page, making it ideal for multilingual websites.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>All options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Number of languages to display</td>
<td><code>1000</code></td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-status</code></td>
<td><code>1</code> = show only active languages, <code>0</code> = show all</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>site_only</strong></td>
<td><code>data-v-site_only</code></td>
<td>Show only languages enabled for the current site</td>
<td><code>true</code></td>
</tr>
<tr>
<td><strong>default</strong></td>
<td><code>data-v-default</code></td>
<td>Preselect a specific language; if not set, uses site default</td>
<td><code>null</code></td>
</tr>
</tbody>
</table>
<p>These options allow you to control which languages appear and how they are filtered.</p>
<hr />
<h2><strong>Component Properties</strong></h2>
<h3><strong>Current Language Properties</strong></h3>
<p>The currently selected language is exposed through <code>data-v-language-info-*</code> attributes:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-language-name</code></td>
<td>Language name (e.g., <em>English</em>)</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-language-slug</code></td>
<td>Language slug (e.g., <code>en</code>)</td>
</tr>
<tr>
<td><strong>code</strong></td>
<td><code>data-v-language-code</code></td>
<td>Language code (e.g., <code>en_US</code>)</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language-language_id</code></td>
<td>Internal language ID</td>
</tr>
<tr>
<td><strong>img</strong></td>
<td><code>data-v-language-img</code></td>
<td>Language flag/icon</td>
</tr>
</tbody>
</table>
<p>These are useful for showing the currently active language in a dropdown or header.</p>
<hr />
<h3><strong>Available Languages (Repeatable)</strong></h3>
<p>Languages are listed inside a <code>data-v-language</code> container.<br />
Each language exposes:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-language-name</code></td>
<td>Language name</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-language-slug</code></td>
<td>URL slug</td>
</tr>
<tr>
<td><strong>code</strong></td>
<td><code>data-v-language-code</code></td>
<td>Language code</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language-language_id</code></td>
<td>Internal ID</td>
</tr>
<tr>
<td><strong>img</strong></td>
<td><code>data-v-language-img</code></td>
<td>Language flag/icon</td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-language-sort_order</code></td>
<td>Display order</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-language-status</code></td>
<td><code>1</code> = active, <code>0</code> = inactive</td>
</tr>
<tr>
<td><strong>default</strong></td>
<td><code>data-v-language-default</code></td>
<td><code>1</code> if default language</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-language-url</code></td>
<td>URL to the translated version of the current page</td>
</tr>
</tbody>
</table>
<p>The <code>url</code> property is especially important:</p>
<ul>
<li>On category/product/post pages, it links to the translated version of that item</li>
<li>On pages without translations, it links to the language homepage</li>
</ul>
<hr />
<h2><strong>Example Usage</strong></h2>
<pre><code class="language-html">&lt;div class=&quot;dropdown&quot; data-v-component-language&gt;
	&lt;form method=&quot;post&quot; enctype=&quot;multipart/form-data&quot; id=&quot;form-language&quot;&gt;

		&lt;a class=&quot;dropdown-toggle nav-link&quot; 
		   data-bs-toggle=&quot;dropdown&quot; 
		   role=&quot;button&quot; 
		   title=&quot;Language&quot; 
		   aria-expanded=&quot;false&quot;&gt;

			&lt;span data-v-language-info-name&gt;&lt;/span&gt;
		&lt;/a&gt;

		&lt;div class=&quot;dropdown-menu&quot;&gt;

			&lt;div data-v-language&gt;
				&lt;button class=&quot;dropdown-item&quot; 
				        type=&quot;submit&quot; 
				        name=&quot;language&quot; 
				        data-v-language-code&gt;

					&lt;img loading=&quot;lazy&quot; 
					     class=&quot;me-1&quot; 
					     data-v-language-img&gt;

					&lt;span data-v-language-name&gt;&lt;/span&gt;
				&lt;/button&gt;
			&lt;/div&gt;

		&lt;/div&gt;
	&lt;/form&gt;
&lt;/div&gt;
</code></pre>
<p>This example creates a dropdown language selector that:</p>
<ul>
<li>Shows the current language</li>
<li>Lists all available languages</li>
<li>Displays flags and names</li>
<li>Submits the selected language code</li>
<li>Automatically links to the translated version of the current page</li>
</ul>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="81">
			<title data-v-post-name="name">Component post</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-post</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Post Component renders a single post anywhere in your theme. It can be used for blog articles, news items, custom post types, or any content stored as a post in Vvveb CMS. The component automatica]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Post Component</strong> renders a single post anywhere in your theme. It can be used for blog articles, news items, custom post types, or any content stored as a post in Vvveb CMS. The component automatically loads the correct post based on ID or slug, or it can be configured manually.</p>
<p>To activate it, add:</p>
<pre><code>data-v-component-post
</code></pre>
<hr />
<h2><strong>Component Options</strong></h2>
<p>Options are added as HTML attributes using the <code>data-v-*</code> syntax. These control which post is loaded and how it is filtered.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>post_id</strong></td>
<td><code>data-v-post_id</code></td>
<td>Load a post by ID. If set to <code>url</code>, the ID is taken from the GET parameter.</td>
<td><code>url</code></td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-slug</code></td>
<td>Load a post by slug. If set to <code>url</code>, the slug is taken from the GET parameter.</td>
<td><code>url</code></td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language for post title and content.</td>
<td>Current language</td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-site_id</code></td>
<td>Site ID to load the post from (for multisite setups).</td>
<td>Current site</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>data-v-type</code></td>
<td>Post type (e.g., <code>post</code>, <code>news</code>, <code>event</code>).</td>
<td><code>post</code></td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-status</code></td>
<td>Filter by post status: <code>publish</code>, <code>draft</code>, <code>pending</code>, <code>private</code>, <code>scheduled</code>.</td>
<td>None</td>
</tr>
<tr>
<td><strong>comment_count</strong></td>
<td><code>data-v-comment_count</code></td>
<td>Include comment count (<code>true/false</code>).</td>
<td><code>false</code></td>
</tr>
<tr>
<td><strong>comment_status</strong></td>
<td><code>data-v-comment_status</code></td>
<td>Filter comments by status: <code>1</code> = published, <code>0</code> = pending, <code>2</code> = spam, <code>3</code> = trash.</td>
<td><code>1</code></td>
</tr>
</tbody>
</table>
<p>These options allow the component to load the correct post and adapt to multilingual, multisite, or custom post‑type setups.</p>
<hr />
<h2><strong>Component Properties</strong></h2>
<p>Inside the component, post data is exposed through <code>data-v-post-*</code> attributes. These can be used to build any layout, from simple blog cards to full article pages.</p>
<h3><strong>Post Fields</strong></h3>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-post-name</code></td>
<td>Post title</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-post-content</code></td>
<td>Full post content</td>
</tr>
<tr>
<td><strong>excerpt</strong></td>
<td><code>data-v-post-excerpt</code></td>
<td>Short excerpt</td>
</tr>
<tr>
<td><strong>status</strong></td>
<td><code>data-v-post-status</code></td>
<td>Post status (<code>publish</code>, <code>disabled</code>, <code>scheduled</code>)</td>
</tr>
<tr>
<td><strong>image</strong></td>
<td><code>data-v-post-image</code></td>
<td>Featured image</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-post-slug</code></td>
<td>Post slug</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-post-url</code></td>
<td>Post detail page URL</td>
</tr>
<tr>
<td><strong>meta_keywords</strong></td>
<td><code>data-v-post-meta_keywords</code></td>
<td>SEO keywords</td>
</tr>
<tr>
<td><strong>meta_description</strong></td>
<td><code>data-v-post-meta_description</code></td>
<td>SEO description</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>data-v-post-type</code></td>
<td>Post type</td>
</tr>
<tr>
<td><strong>password</strong></td>
<td><code>data-v-post-password</code></td>
<td>Password for protected posts</td>
</tr>
<tr>
<td><strong>comment_status</strong></td>
<td><code>data-v-post-comment_status</code></td>
<td>Whether comments are allowed</td>
</tr>
<tr>
<td><strong>comment_count</strong></td>
<td><code>data-v-post-comment_count</code></td>
<td>Number of comments</td>
</tr>
<tr>
<td><strong>views</strong></td>
<td><code>data-v-post-views</code></td>
<td>Number of views</td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-post-sort_order</code></td>
<td>Sort order</td>
</tr>
<tr>
<td><strong>template</strong></td>
<td><code>data-v-post-template</code></td>
<td>Template used to render the post</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>HTML Example</strong></h2>
<pre><code class="language-html">&lt;div data-v-component-post 
     data-v-slug=&quot;hello-world&quot;&gt;

    &lt;img data-v-post-image alt=&quot;Post image&quot;&gt;

    &lt;h1 data-v-post-name&gt;Post name placeholder&lt;/h1&gt;

    &lt;span data-v-post-excerpt&gt;Lorem ipsum&lt;/span&gt;

    &lt;div data-v-post-content&gt;Lorem ipsum&lt;/div&gt;

&lt;/div&gt;
</code></pre>
<p>This example loads the post with the slug <strong>hello-world</strong> and displays its image, title, excerpt, and full content.</p>
<hr />
<p>If you’re building a blog layout or a custom post type template, it helps to decide whether you want the component to auto-detect the post from the URL or always load a specific one.</p>
]]></content:encoded>		
		</item><item data-v-post="post" data-v-id="83">
			<title data-v-post-name="name">Component menu</title>
			<link data-v-post-full-url="name">https://dev.vvveb.com/component-menu</link>
			<dc:creator data-v-post-display_name="name"><![CDATA[Admin]]></dc:creator>
			<pubDate data-v-post-pubDate="date">Sat, 20 Jan 2024 00:35:33 +0000</pubDate>
			<category data-v-post-category-name="category" data-filter-cdata=""><![CDATA[Category]]></category>
			<description data-v-post-excerpt="excerpt" data-filter-cdata=""><![CDATA[The Menu Component displays a list of menu items and is used to build navigation structures such as headers, footers, sidebars, mobile menus, or mega‑menus. 
To activate the component, add the attri]]></description>
			<content:encoded data-v-post-content="content" data-filter-cdata=""><![CDATA[
<p>The <strong>Menu Component</strong> displays a list of menu items and is used to build navigation structures such as headers, footers, sidebars, mobile menus, or mega‑menus.</p>
<p>To activate the component, add the attribute:</p>
<pre><code>data-v-component-menu
</code></pre>
<p>The component supports nested (recursive) menu structures and automatically loads the correct menu based on <code>menu_id</code>, <code>slug</code>, site, and language.</p>
<hr />
<h2><strong>Component Options</strong></h2>
<p>All options are added as HTML attributes using the <code>data-v-*</code> syntax.</p>
<table class="table">
<thead>
<tr>
<th>Option</th>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>start</strong></td>
<td><code>data-v-start</code></td>
<td>Starting offset for pagination</td>
<td><code>1</code></td>
</tr>
<tr>
<td><strong>limit</strong></td>
<td><code>data-v-limit</code></td>
<td>Maximum number of menu items to display</td>
<td><code>1000</code></td>
</tr>
<tr>
<td><strong>menu_id</strong></td>
<td><code>data-v-menu_id</code></td>
<td>ID of the menu to load</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-slug</code></td>
<td>Menu slug (useful for multi‑site setups)</td>
<td><code>null</code></td>
</tr>
<tr>
<td><strong>site_id</strong></td>
<td><code>data-v-site_id</code></td>
<td>Site ID to load the menu from</td>
<td>Current site</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-language_id</code></td>
<td>Language ID for menu item names/content</td>
<td>Current language</td>
</tr>
</tbody>
</table>
<h3><strong>Multi‑Site Behavior</strong></h3>
<p>Multiple sites can use the same menu slug (e.g., <code>main-menu</code>) but have different menu content.<br />
This allows a shared theme to load a site‑specific menu simply by using:</p>
<pre><code>data-v-slug=&quot;main-menu&quot;
</code></pre>
<hr />
<h2><strong>Component Structure &amp; Properties</strong></h2>
<p>Inside the component, menu items are rendered using:</p>
<ul>
<li><code>data-v-menu-items</code> — container for the list</li>
<li><code>data-v-menu-item</code> — repeatable element for each menu entry</li>
<li><code>data-v-menu-item-recursive</code> — container for nested child items</li>
</ul>
<h3><strong>Menu Item Properties</strong></h3>
<p>Each menu item exposes the following attributes:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>name</strong></td>
<td><code>data-v-menu-item-name</code></td>
<td>Menu item label</td>
</tr>
<tr>
<td><strong>slug</strong></td>
<td><code>data-v-menu-item-slug</code></td>
<td>Slug for post/page/product items</td>
</tr>
<tr>
<td><strong>content</strong></td>
<td><code>data-v-menu-item-content</code></td>
<td>Custom content (for text or HTML menu items)</td>
</tr>
<tr>
<td><strong>parent_id</strong></td>
<td><code>data-v-menu-item-parent_id</code></td>
<td>Parent menu item ID (for nested menus)</td>
</tr>
<tr>
<td><strong>menu_item_id</strong></td>
<td><code>data-v-menu-item-menu_item_id</code></td>
<td>Internal menu item ID</td>
</tr>
<tr>
<td><strong>children</strong></td>
<td><code>data-v-menu-item-children</code></td>
<td>Number of child items</td>
</tr>
<tr>
<td><strong>language_id</strong></td>
<td><code>data-v-menu-item-language_id</code></td>
<td>Language ID for multilingual menus</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td><code>data-v-menu-item-type</code></td>
<td>Menu item type: <code>link</code>, <code>text</code>, <code>post</code>, <code>page</code>, <code>product</code>, <code>home</code>, <code>blog</code>, <code>shop</code></td>
</tr>
<tr>
<td><strong>img</strong></td>
<td><code>data-v-menu-item-img</code></td>
<td>Menu item image (optional)</td>
</tr>
<tr>
<td><strong>sort_order</strong></td>
<td><code>data-v-menu-item-sort_order</code></td>
<td>Display order</td>
</tr>
<tr>
<td><strong>url</strong></td>
<td><code>data-v-menu-item-url</code></td>
<td>Final URL for the menu item</td>
</tr>
</tbody>
</table>
<p>These properties allow full control over how each menu item is displayed.</p>
<hr />
<h2><strong>Example Usage</strong></h2>
<pre><code class="language-html">&lt;div class=&quot;collapse navbar-collapse&quot; 
     id=&quot;navbar&quot; 
     data-v-component-menu=&quot;header&quot; 
     data-v-slug=&quot;main-menu&quot;&gt;

  &lt;ul class=&quot;navbar-nav&quot; data-v-menu-items&gt;

    &lt;!-- Top-level menu item --&gt;
    &lt;li class=&quot;nav-item&quot; data-v-menu-item&gt;

      &lt;a class=&quot;nav-link&quot; data-v-menu-item-url&gt;
        &lt;span data-v-menu-item-name&gt;&lt;/span&gt;
        &lt;span data-v-menu-item-content&gt;
          &lt;img src=&quot;/media/vvveb.svg&quot; height=&quot;24&quot; alt=&quot;&quot; class=&quot;me-2&quot;&gt;Mega menu
        &lt;/span&gt;
      &lt;/a&gt;

      &lt;!-- Recursive submenu --&gt;
      &lt;div class=&quot;dropdown-menu&quot; data-v-menu-item-recursive&gt;
        &lt;div data-v-menu-item class=&quot;nav-item&quot;&gt;
          &lt;a class=&quot;dropdown-item&quot; data-v-menu-item-url&gt;
            &lt;span data-v-menu-item-name data-v-if-not=&quot;category.type = 'text'&quot;&gt;&lt;/span&gt;
            &lt;span data-v-menu-item-content data-v-if=&quot;category.content&quot;&gt;
              &lt;img src=&quot;/media/vvveb.svg&quot; height=&quot;24&quot; alt=&quot;&quot; class=&quot;me-2&quot;&gt;Mega menu
            &lt;/span&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/li&gt;

    &lt;!-- Another menu item --&gt;
    &lt;li class=&quot;nav-item&quot; data-v-menu-item&gt;
      &lt;a class=&quot;nav-link&quot; data-v-menu-item-url&gt;
        &lt;span data-v-menu-item-name&gt;Contact&lt;/span&gt;
      &lt;/a&gt;
    &lt;/li&gt;

  &lt;/ul&gt;
&lt;/div&gt;
</code></pre>
<p>This example demonstrates:</p>
<ul>
<li>A main navigation menu</li>
<li>Recursive dropdown support</li>
<li>Custom content inside menu items</li>
<li>Automatic URL generation</li>
</ul>
]]></content:encoded>		
		</item>		
		
		
		
	</channel>
</rss>
