Quickstarters
How to Build a Qwik Frontend and Connect It to a Backend?
31 min
in this tutorial, you’ll build a to do list application using qwik and connect it to a robust backend powered by back4app this guide is tailored for developers who want to harness qwik’s resumability and lazy loading capabilities while integrating essential crud (create, read, update, delete) operations with a managed backend by the end, you’ll have a fully functional application that demonstrates how to combine a modern qwik frontend with back4app’s reliable backend services building a full stack application can be challenging because it involves backend setup, database management, authentication, and deployment to simplify these tasks, we use back4app— a scalable backend as a service (baas) solution—so you can concentrate on building your qwik app while it takes care of hosting, databases, and apis back4app delivers a comprehensive suite of backend services, including a ready to use nosql database, authentication, cloud code for server side logic, and smooth sdk integrations its containerized deployment support makes it an excellent choice for modern full stack applications with these tools at your fingertips, you can rapidly develop and deploy applications without the overhead of managing server infrastructure key takeaways by following this tutorial you will learn to initialize a modern qwik project integrate a backend service to manage your application’s data implement essential crud operations for an interactive user interface deploy a fully functional to do list application using containerized workflows on back4app prerequisites before you begin, ensure you have the following node js and npm install the latest lts version from nodejs org https //nodejs org/ and verify with node v and npm v basic qwik knowledge familiarity with qwik’s components, signals (using usesignal ), and its resumability concept is recommended if you’re new to qwik, review its documentation first a back4app account sign up at back4app https //www back4app com/ to set up and manage your backend services with these prerequisites in place, you’re ready to set up your project and start building project setup begin by setting up your local development environment and initializing your qwik project confirm that node js (lts version) is installed node v npm v create a new qwik project using the qwik cli run the following command npm create qwik\@latest answer the prompts that the cli will provide name the project todo app or replace it with whatever name you prefer change into your project directory cd todo app start the development server to verify your setup npm start your qwik app should now be running locally open the provided url in your browser to confirm next, you’ll configure your backend on back4app to manage data storage and api interactions creating the todo backend back4app offers a fully managed backend service powered by parse this service provides a nosql database, authentication, cloud code, and auto generated apis out of the box this section guides you through creating a task data model to store your to do items and linking it with your qwik frontend setting up your backend application log in to your back4app dashboard https //www back4app com/ and click "create a new app " name your application (for example, todoqwikapp ) and select nodejs/parse as the backend type once created, navigate to "database" > "browser" click "create a class" and choose "custom" name the class task and set the class level permissions to allow public read and write (you can refine these settings later) in the task class, add the following fields title (string) – the title of the task description (string) – details about the task completed (boolean) – indicates whether the task is completed duedate (date) – the deadline for the task click "save" to finalize your schema integrating back4app with qwik integrate back4app into your qwik project using the parse javascript sdk install the sdk via npm npm install parse configure the sdk by initializing it with your application id and javascript key retrieve these credentials from your back4app dashboard under app settings > security & keys create a configuration file (for example, src/lib/parse js ) and add the following import parse from "parse/dist/parse min js"; const parse app id = 'your application id'; const parse js key = 'your javascript key'; const parse server url = 'https //parseapi back4app com/'; parse initialize(parse app id, parse js key); parse serverurl = parse server url; export default parse; you can now import this configuration in your qwik components and routes to interact with your backend developing the frontend with qwik now that your backend is connected, build the user interface for your to do list application using qwik you’ll create components to add, display, update, and delete tasks while managing state with qwik signals organizing your components your application will include the following key components taskform tsx – a component to handle adding new tasks tasklist tsx – a component to display all tasks and provide controls for marking tasks complete or deleting them taskitem tsx – a component that represents an individual task with actions to toggle completion or remove it create a components folder inside src and add these files mkdir src/components touch src/components/taskform tsx src/components/tasklist tsx src/components/taskitem tsx managing state with qwik signals utilize qwik’s usesignal for reactive state management in your main page (for example, src/routes/index tsx ), set up the state and data fetching as follows import { component$, usesignal, usevisibletask$, $ } from '@builder io/qwik'; import parse from ' /lib/parse js'; import taskform from ' /components/taskform'; import tasklist from ' /components/tasklist'; export default component$(() => { const tasks = usesignal< { id string; createdat string; updatedat string; title string; description string; completed boolean; }\[] \>(\[]); const fetchtasks = $ ( async () => { try { const task = parse object extend("task"); const query = new parse query(task); const results = await query find(); tasks value = results map(task => ({ id task id ?? '', createdat task createdat ? task createdat toisostring() '', updatedat task updatedat ? task updatedat toisostring() '', title task get('title') ?? '', description task get('description') ?? '', completed task get('completed') ?? false, })); } catch (error) { console error("error fetching tasks ", error); } }); usevisibletask$(async () => { await fetchtasks(); }); return ( \<div class="container"> \<h1>to do list\</h1> \<taskform ontaskadded$={fetchtasks} /> \<tasklist tasks={tasks value} ontaskschange$={fetchtasks} /> \</div> ); }); building the task form component in src/components/taskform tsx , create a form component to add tasks use qwik’s reactive signals for form inputs import { component$, usesignal, $, qrl } from '@builder io/qwik'; import parse from ' /lib/parse js'; interface taskformprops { ontaskadded$ qrl<() => void>; } export default component$((props taskformprops) => { const title = usesignal(''); const description = usesignal(''); const handlesubmit$ = $(async (e event) => { e preventdefault(); try { const task = parse object extend("task"); const task = new task(); task set("title", title value); task set("description", description value); task set("completed", false); await task save(); title value = ''; description value = ''; return true; } catch (error) { console error("error adding task ", error); return false; } }); return ( \<form preventdefault\ submit onsubmit$={async (event) => { const success = await handlesubmit$(event); if (success) { await props ontaskadded$(); } }} \> \<input type="text" placeholder="task title" value={title value} oninput$={(e) => title value = (e target as htmlinputelement) value} required /> \<input type="text" placeholder="description" value={description value} oninput$={(e) => description value = (e target as htmlinputelement) value} required /> \<button type="submit">add task\</button> \</form> ); }); building the task list and item components in src/components/tasklist tsx , render the list of tasks import { component$ } from '@builder io/qwik'; import taskitem from ' /taskitem'; interface task { id string; title string; description string; completed boolean; } interface tasklistprops { tasks task\[]; ontaskschange$ () => void; } export default component$((props tasklistprops) => { return ( \<div> {props tasks length === 0 ? ( \<p>no tasks available\</p> ) ( props tasks map(task => ( \<taskitem key={task id} task={task} ontaskschange$={props ontaskschange$} /> )) )} \</div> ); }); in src/components/taskitem tsx , create a component for individual tasks with actions to toggle completion or delete the task import { component$, $ } from '@builder io/qwik'; import parse from ' /lib/parse js'; interface task { id string; title string; description string; completed boolean; } interface taskitemprops { task task; ontaskschange$ () => void; } export default component$((props taskitemprops) => { const handletoggle = $(async () => { try { const query = new parse query("task"); const tasktoupdate = await query get(props task id); tasktoupdate set("completed", !props task completed); await tasktoupdate save(); props ontaskschange$(); } catch (error) { console error("error updating task ", error); } }); const handledelete = $(async () => { try { const query = new parse query("task"); const tasktodelete = await query get(props task id); await tasktodelete destroy(); props ontaskschange$(); } catch (error) { console error("error deleting task ", error); } }); return ( \<div class={`task item ${props task completed ? "completed" ""}`}> \<h3>{props task title}\</h3> \<p>{props task description}\</p> \<button onclick$={handletoggle}> {props task completed ? "undo" "complete"} \</button> \<button onclick$={handledelete}>delete\</button> \</div> ); }); styling your application create a src/global css file to add basic styling / src/global css / container { max width 600px; margin 40px auto; padding 0 20px; text align center; font family sans serif; } container h1 { margin bottom 20px; } form { display flex; flex direction column; align items center; gap 10px; margin bottom 20px; } form input\[type="text"] { width 80%; max width 400px; padding 8px; box sizing border box; font size 1rem; } form button { padding 8px 16px; cursor pointer; font size 1rem; border none; background color #eaeaea; transition background color 0 2s ease; } form button\ hover { background color #ccc; } container p { font size 1rem; } task item { display flex; flex direction column; align items center; justify content center; gap 12px; border 1px solid #ccc; border radius 6px; padding 15px; margin 10px 0; background color #fafafa; text align center; transition background color 0 2s ease; } task item completed h3, task item completed p { text decoration line through; color #888; } task item h3 { margin 0; font size 1 1rem; } task item p { margin 0; font size 1rem; } task item button { padding 6px 12px; border none; background color #eaeaea; cursor pointer; font size 0 9rem; } task item button\ hover { background color #ccc; } @media (min width 600px) { task item { flex direction row; } } import the global styles in your root file (e g , src/root tsx ) import " /global css"; finalizing the ui your qwik to do list application now features a dynamic frontend integrated with back4app and custom styling the app allows you to add, display, update, and delete tasks while ensuring smooth communication between the frontend and backend next, you’ll deploy your qwik application using back4app’s web deployment platform deploying the frontend on back4app web deployment back4app web deployment provides a fully managed, containerized environment for hosting your applications with docker based deployments, you can package your qwik app and deploy it seamlessly add the express server adapter qwik lets you configure deployment adapters for specific targets we'll add the express adapter to serve your project in production install the adapter npm run qwik add then select adapter node js express server and confirm the installation this updates your readme and adds new deployment scripts in your package json update the start script open package json and change the start script to "start" "node server/entry express" optionally, keep a separate development script if needed this ensures your project uses express to serve the production build configuring qwik for production build your production ready qwik site with npm run build creating a dockerfile for your app create a dockerfile in the project root to containerize your qwik application \# build stage from node\ lts alpine as builder user node workdir /home/node copy package json run npm ci copy chown=node\ node run npm run build \# final run stage from node\ lts alpine as runner env node env=production user node workdir /home/node copy from=builder chown=node\ node /home/node/package json copy from=builder chown=node\ node /home/node/node modules /node modules copy from=builder chown=node\ node /home/node/dist /dist copy from=builder chown=node\ node /home/node/server /server arg port expose ${port 3000} cmd \["node", "server/entry express"] pushing to github and deploying via back4app push your project to github git init git add git commit m "initial commit for back4app deployment" git branch m main git remote add origin \<your github repository url> git push u origin main then, deploy using back4app web deployment log in to back4app web deployment https //www back4app com/containers click "create new app" , provide a name, and select github repository authorize back4app to access your repository and select your qwik project repo choose dockerfile deployment and confirm the build settings click "deploy" to initiate the build process monitoring and managing deployments after deployment, use the back4app dashboard to view logs for troubleshooting monitor container performance and resource usage trigger redeployments when new commits are pushed configure custom domains if needed testing and debugging your application once deployed, thoroughly test your qwik app verify api connectivity open your browser’s developer console (f12 → network) to check api calls during task operations add and retrieve tasks use the ui to add tasks, then refresh to confirm data persistence in the back4app database browser test crud operations ensure that marking tasks complete and deletion reflect correctly in the backend handle edge cases validate form inputs and simulate slow network conditions using developer tools if issues arise, review the back4app logs or double check your api configuration best practices for using back4app services enhance your application’s performance and security by optimizing api calls use batch requests for multiple operations and query only the necessary fields securing sensitive data store credentials like application id and javascript key in environment variables in qwik, create a env file vite parse app id=your app id vite parse js key=your js key enabling auto scaling activate auto scaling in back4app web deployment to manage high traffic enhancing security restrict class level permissions (clps) to control data modifications and set up acls as needed utilizing cloud code offload complex logic to cloud code for improved performance and reduced api exposure conclusion you have now built a full stack to do list application using qwik for the frontend and back4app’s robust backend services this tutorial guided you through setting up a qwik project, integrating the parse sdk, and deploying your site using containerized workflows on back4app as you continue developing, consider adding features such as advanced user authentication, real time updates, and third party integrations for further information and support, refer to the back4app documentation https //www back4app com/docs