Vue 3 Click & Drop Page Builder. Power your vision and build impressive pages. The web builder for stunning pages. Enable users to design and publish modern pages at any scale. Build responsive pages like listings, jobs or blog posts and manage content easily.
Play around with the page builder
This app was born out of my desire to create a minimalist page builder with an elegant and intuitive design.
The web builder for stunning pages. Enable users to design and publish modern pages at any scale. Build responsive pages like listings, jobs or blog posts and manage content easily using the free Click & Drop Page Builder.
To star the repository, simply click on the Star button located at the top-right corner of the GitHub page. Thank you in advance for your support! 🙌
Introducing the Free Vue Click & Drop Page Builder
create and enhance digital experiences with Vue on any backend.
Play around with the page builder
A Page Builder designed for growth. Build your website pages with ready-made components that are fully customizable and always responsive, designed to fit every need. A powerful Page Builder for growing merchants, brands, and agencies.
Includes:
The Page Builder is packed with features:
Powerful Page Builder for any growing merchants, brands, &
agencies. Empower users to create the perfect content with the Page Builder.
Please note that these instructions assume you have Node.js installed.
Make sure to install the dependencies:
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
I have separated all the logic for manipulating the HTML elements into its own PageBuilder class, which can be found at the path: src/composables/PageBuilder.js
.
Customizing the page builder is made simple since all the logic resides in the PageBuilder Class.
<script setup>
const mediaLibraryStore = useMediaLibraryStore();
const pageBuilderStateStore = usePageBuilderStateStore();
const userStore = useUserStore();
const openPageBuilder = ref(false);
const pageBuilderPrimaryHandler = ref(null);
const pageBuilderSecondaryHandler = ref(null);
const pageBuilder = new PageBuilder(pageBuilderStateStore, mediaLibraryStore);
const formType = ref('create');
const getIsLoading = computed(() => {
return userStore.getIsLoading;
});
const pathPageBuilderStorageCreate = `page-builder-create-post`;
const resourceId = 1;
const pathPageBuilderStorageUpdate = `page-builder-update-post-id-${resourceId}`;
const handlePageBuilder = async function () {
userStore.setIsLoading(true);
await nextTick();
openPageBuilder.value = true;
if (formType.value === 'create') {
pageBuilderStateStore.setComponents([]);
pageBuilder.areComponentsStoredInLocalStorage();
}
// handle click
pageBuilderPrimaryHandler.value = async function () {
userStore.setIsLoading(true);
if (formType.value === 'update') {
await nextTick();
pageBuilder.saveComponentsLocalStorageUpdate();
}
openPageBuilder.value = false;
userStore.setIsLoading(false);
};
// handle click
pageBuilderSecondaryHandler.value = async function () {
userStore.setIsLoading(true);
// save to local storage if new resource
if (formType.value === 'create') {
await nextTick();
pageBuilder.saveComponentsLocalStorage();
await nextTick();
}
// save to local storage if update
if (formType.value === 'update') {
await nextTick();
pageBuilder.synchronizeDOMAndComponents();
await nextTick();
}
openPageBuilder.value = false;
userStore.setIsLoading(false);
};
userStore.setIsLoading(false);
// end modal
};
// Builder # End
const handleDraftForUpdate = async function () {
userStore.setIsLoading(true);
if (formType.value === 'update') {
await nextTick();
pageBuilder.areComponentsStoredInLocalStorageUpdate();
await nextTick();
pageBuilder.setEventListenersForElements();****
userStore.setIsLoading(false);
}
};
onBeforeMount(() => {
pageBuilderStateStore.setLocalStorageItemName(pathPageBuilderStorageCreate);
pageBuilderStateStore.setLocalStorageItemNameUpdate(
pathPageBuilderStorageUpdate
);
});
</script>
<template>
<PageBuilderModal
:show="openPageBuilder"
updateOrCreate="create"
@pageBuilderPrimaryHandler="pageBuilderPrimaryHandler"
@pageBuilderSecondaryHandler="pageBuilderSecondaryHandler"
@handleDraftForUpdate="handleDraftForUpdate"
>
<PageBuilderView></PageBuilderView>
</PageBuilderModal>
</template>
Each Page Builder draft is automatically saved to local storage, allowing you to resume your work later. This process differs slightly depending on whether you are creating a new resource like a blog post, job ad, or listing, or updating an existing resource.
When creating a new resource like a blog post, job ad, or listing, you need to specify a name for the local storage item that will store the draft. This is done as follows:
const pathPageBuilderStorageCreate = `page-builder-create-post`;
onBeforeMount(() => {
// Define local storage key name before on mount
pageBuilderStateStore.setLocalStorageItemName(pathPageBuilderStorageCreate);
});
For updating an existing resource like a blog post, job ad, or listing, you must first obtain the blog post ID and then save a name that includes this ID to local storage. This way, the Page Builder can find the exact resource from local storage later on when the user wants to continue editing the resource with the unique ID:
const resourceId = 1;
const pathPageBuilderStorageUpdate = `page-builder-update-post-id-${resourceId}`;
onBeforeMount(() => {
// Define local storage key name before on mount
pageBuilderStateStore.setLocalStorageItemNameUpdate(
pathPageBuilderStorageUpdate
);
});
In both cases, the pageBuilderStateStore is responsible for handling the local storage name, ensuring that the correct draft is stored and retrieved as needed.
If Creating new components, please always add the HTML inside section tags.
<section>
<div>
<p>New components</p>
</div>
</section>
HTML components are currently stored in a JSON file named components.json
in the root directory. HTML components can also be easily stored in the database, resulting in better management. Simply provide the setLoadComponents
method with the new URL for loading components from the backend.
Please note that if you want to use Unsplash, simply create an .env file in your root folder and enter your Unsplash API key and value.
Example: VITE_UNSPLASH_KEY=“your-unsplash-api-key-here”
Get your unsplash api key here.
The Page builder’s capabilities become infinite when integrated with a backend.
If you’re familiar with Laravel, the Page Builder is already integrated with the open-source Laravel Free Listing Directory, Blog & Job Board Theme, which is available at:
demo & repo.
By utilizing a backend Framework, the HTML components, currently stored in a JSON file at components.json
, can be easily stored in the database, resulting in better management of HTML components.
If you have any questions or if you’re looking for customization, feel free to connect with me on LinkedIn and send me a message.
Thank you for considering contributing to this project!