<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="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="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>		
		
		
		
	</channel>
</rss>
