Astro is a recently popular web development technology. It's a multi-page application (MPA) framework that allows apps to load with no JavaScript, providing the benefits of modern frameworks like Next.js, but with the performance of traditional MPAs. Its "islands architecture" lets you choose when to load your JavaScript code. Additionally, Astro enables you to use multiple frameworks within a single application, making it a highly versatile option for web developers.
Setting up Development Environment
To complete this tutorial, ensure you have installed the following tools and utilities on your local development environment.
- VsCode
- NodeJS
- Astro
- You also need an Altogic Account. If you do not have one, you can create an account by signin up for Altogic.
Creating an Altogic Account
After creating an account, you will see the workspace and repository page. You can create a new app by clicking the + New app
button.
Click + New app
and follow the instructions;
- In the App name field, enter a name for the app.
- Enter your subdomain.
- Choose the deployment location.
- And select your free execution environment pricing plan.
For this tutorial, we will use the blank template. So, select the Blank template and click Next
.
note
In the template section, you can choose the template you want to use. Basic template creates a default user data model for your app, which is required by Altogic Client Library to store user data and manage authentication. If you don't need authentication, you can use the Blank template.
Later, if you want, you can easily create a new data model manually and from the App Settings → Authentication mark this new data model as your user data model.
Awesome! We have created our application; Now click/tap on the newly created app to launch the Designer. In order to access the app and use the Altogic client library, we should get envUrl
and clientKey
of this app.
Click the Home section in the left menu and copy the API base URL and Master client key for your app.
info
In this tutorial we don't need authentication. So, let's disable session based authentication from the App Settings → Client library keys → Master client key view of Altogic Designer.
By clicking the Enforce session
checkbox, you can disable session based authentication. Now, we are ready to start building our app
Creating an Astro Project
Open your terminal and navigate to the directory where you want to create your project. Then run the following command to create an Astro project.
npm create astro@latest
Installing React into our Astro Project
After creating our Astro Project, we need to install ReactJs into it to use react components and hooks.
# Using NPM
npx astro add react
# Using Yarn
yarn astro add react
# Using PNPM
pnpm astro add react
Installing Tailwind into our Astro Project
# Using NPM
npx astro add tailwind
# Using Yarn
yarn astro add tailwind
# Using PNPM
pnpm astro add tailwind
Creating .env File, and Astro Settings
In Astro, .env
file variables must start with PUBLIC to access from client side of the application. If you want to initiliaze your Altogic instance in a file, you must put a PUBLIC prefix to your env variables.
PUBLIC_ALTOGIC_ENV_URL=YOUR_ENV_URL
PUBLIC_ALTOGIC_CLIENT_KEY=YOUR_CLIENT_KEY
Also, for server-side rendering and building non-static site we must declare that it in our astro.config.mjs
file.
import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
// https://astro.build/config
import react from "@astrojs/react";
// https://astro.build/config
import tailwind from "@astrojs/tailwind";
// https://astro.build/config
export default defineConfig({
site: "https://example.com",
integrations: [mdx(), sitemap(), react(), tailwind()],
output: "server", // This must be declared
});
Creating the Backend
As we mentioned earlier, we will use Altogic to create the backend for our app. Altogic is a serverless backend as a service platform that provides authentication, database, and other services. You can create a free account on Altogic and create a new app.
Creating Blog Model
- Click/tap on Models on the left sidebar.
- Click New on the right of the screen and select model.
- Set model name as blog.
- Ensure that the Enable timestamps is selected.
- Click Next

With using Altogic you can automatically generate Rest API for your models. You can also create custom API endpoints.

We have created a blog model, now we need to add fields for to our model.
_id
Unique object id
content
Blog content in text
createdAt
Data created time
updatedAt
Data last updated time
title
Blog title
coverImage
Image URL of blog’s cover image
slug
Blog slug ( Generated by title and index field with “Default value expression” )
index
Unique index number for slug
To create unique slug’s you can use Altogic’s “Default value expression”. You can generate unique slugs with unique id’s with the following function.
REPLACE(
REPLACE(TOLOWER(IF(this.title, this.title, "story")), " ", "-"),
"?",
""
) +
"-" +
SUM(this.index, 14152);

Integrating Frontend with Backend
Now we have a basic UI for our app and a database design. Let’s integrate our Astro app with the backend. We will use Altogic Client Library to integrate our frontend with the backend.
Installing Altogic Client Library
You can install the Altogic Client Library with using npm or yarn. Open your project directory and run the following command to install the Altogic Client Library.
# using npm
npm install altogic
# OR is using yarn
yarn add altogic
Let’s create a utils/
folder in the root of the project directory and create a altogic.ts
file in the utils/
folder.
Open altogic.ts
and paste below code block to export the altogic client instance
After finishing our settings, we can create our Altogic instance and prepare for CRUD operations.
altogic.ts
import { createClient } from "altogic";
const altogic = createClient(
import.meta.env.PUBLIC_ALTOGIC_ENV_URL,
import.meta.env.PUBLIC_ALTOGIC_CLIENT_KEY
);
export const { db, auth, storage, endpoint, queue, realtime, cache } = altogic;
NOTE
You can find your envUrl
and clientKey
in the Home or Settings view of your app. You can also create a new environment and get the envUrl
and clientKey
for the new environment.
Disabling Session Requirement for Altogic Client Library
Since there are no users in this application, we need to disable Altogic Client Library’s session requirement.
To disable session requirement:
1- Go to Settings on Your Altogic Designer
You can find the settings on your Altogic Designer’s side menu on the left.

2- Select Client Library Keys
When you open the page, a menu will be appeared on the left. Click on Client library keys on the left menu.

3- Click on Your Active Key
Click on your active key. By default it’s Master client key.

4- Disable Enforce Session
When you disable your enforce session and save your settings, you can use all db operations without session requirement.

Creating React Components in .astro Files
After installing the necessary packages and configuring our settings, we can create our .jsx extension React components. After creating the component that lists our blogs with React, as shown below, we call it in our index.astro file. When calling it, the point we need to pay attention to is to provide the component with the prop client:load
If we don't provide this prop, our functions inside the component will not work properly.
---
import BaseHead from "../components/BaseHead.astro";
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
import { SITE_TITLE, SITE_DESCRIPTION } from "../consts";
import HeroSection from "../sections/HeroSection.astro";
import BlogList from "../components/BlogList";
---
<!DOCTYPE html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header />
<HeroSection />
<div class="flex-col gap-10 px-10 text-center w-full flex justify-center items-center">
<h2 class="font-bold text-center text-[35px] w-full">From the blog</h2>
<p class="w-[60%] text-center py-5 text-gray-500">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</p>
<BlogList client:load />
</div>
<Footer />
</body>
</html>
import { useEffect, useState } from "react";
import BlogCard from "./BlogCard.jsx";
import { db } from "../utils/altogic.ts";
export default function BlogList() {
const [blogs, setBlogs] = useState([]);
const getBlogs = async () => {
return await db.model("blog").get();
};
useEffect(() => {
getBlogs().then((blogs) => {
setBlogs(blogs.data);
});
}, []);
return (
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 items-center w-full justify-center gap-14 text-start mb-20">
{blogs.length > 0 && blogs.map((blog) => <BlogCard blog={blog} />)}
</div>
);
}
Creating a Blog
At first to create a blog, we first need to build a page with astro.
---
import BaseHead from "../components/BaseHead.astro";
import CreatePost from "../components/CreatePost";
import Header from "../components/Header.astro";
---
<html lang="en">
<head>
<BaseHead
title={"Write a Story"}
description={"You can create a blog here"}
/>
</head>
<body>
<Header />
<div
class="w-full h-[100h] flex flex-col items-center justify-center py-20"
>
<CreatePost client:load />
</div>
</body>
</html>
After we create our .astro page, we can implement a React component inside it. Astro allows us to implement different components with different frameworks into one page.
import { useEffect, useState } from "react";
import { endpoint, storage } from "../utils/altogic.ts";
import { toast } from "react-toastify";
export default function CreatePost() {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [loading, setLoading] = useState(false);
const [file, setFile] = useState();
const [imagePreview, setImagePreview] = useState();
const handleUpload = () => {
document.getElementById("fileUpload").click();
};
const createStory = async (e) => {
e.preventDefault();
setLoading(true);
const { data } = await uploadImage(title, file);
if (data) {
await endpoint
.post("/blog", {
title,
content,
coverImage: data.publicPath,
})
.then((res) => {
if (res) {
alert("Blog Created");
setFile(null);
setTitle("");
setContent("");
}
});
}
};
const uploadImage = async (fileName, file) => {
return await storage.bucket("root").upload(fileName, file);
};
useEffect(() => {
if (file) {
setImagePreview(URL.createObjectURL(file));
}
}, [file]);
return (
<form
class="w-100 h-100 shadow-lg flex flex-col gap-5 p-10"
onSubmit={createStory}
>
<input
onChange={(e) => setFile(e.target.files[0])}
id="fileUpload"
type="file"
hidden
/>
<div
onClick={handleUpload}
class=" cursor-pointer w-full h-48 border-gray-200 border-2 flex justify-center items-center text-gray-600 "
>
{file ? (
<img
class="w-96 h-full overflow-hidden object-cover"
src={imagePreview}
></img>
) : (
<span>Add Image</span>
)}
</div>
<span>Story Title</span>
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
class="w-96 border-2 h-10 px-2"
type="text"
/>
<span>Story Content</span>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
class="w-96 border-2 h-80 resize-none p-2"
></textarea>
<button
disabled={loading}
type="submit"
class="w-full bg-blue-500 h-10 text-white"
>
{loading ? "Loading..." : "Publish"}
</button>
</form>
);
}
To create a blog, we need three fields: title, content and coverImage. Our blog slug will be generated automatically based on title.

After the user fills the input fields and publishes the blog, the cover image will first be stored in the Altogic store, and when the public path is returned a, data will be created according to the blog
model we mentioned above with create endpoint, which Altogic Client Library provides.
Displaying Blogs

Altogic Client Library provides different ways of data fetching. For displaying all the blogs, we will use db
feature.
At first we need to build our landing page with astro. After we create basic fields, we can implement our React component, where we will fetch and display our data.
---
import BaseHead from "../components/BaseHead.astro";
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
import { SITE_TITLE, SITE_DESCRIPTION } from "../consts";
import HeroSection from "../sections/HeroSection.astro";
import BlogList from "../components/BlogList";
---
<!DOCTYPE html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header />
<HeroSection />
<div class="flex-col gap-10 px-10 text-center w-full flex justify-center items-center">
<h2 class="font-bold text-center text-[35px] w-full">From the blog</h2>
<p class="w-[60%] text-center py-5 text-gray-500">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
</p>
<BlogList client:load />
</div>
<Footer />
</body>
</html>
import { useEffect, useState } from "react";
import BlogCard from "./BlogCard.jsx";
import { db } from "../utils/altogic.ts";
export default function BlogList() {
const [blogs, setBlogs] = useState([]);
const getBlogs = async () => {
return await db.model("blog").get();
};
useEffect(() => {
getBlogs().then((blogs) => {
setBlogs(blogs.data);
});
}, []);
return (
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 items-center w-full justify-center gap-14 text-start mb-20">
{blogs.length > 0 && blogs.map((blog) => <BlogCard blog={blog} />)}
</div>
);
}
In this component we will fetch all the blogs in our database and when the data is returned we can display it one by one with the component called BlogCard
.
BlogCard component takes blog data as a prop and displays all the necessary fields.
export default function BlogCard({ blog }) {
return (
<div
onClick={() => navigation.navigate(`/blog/${blog.slug}`)}
class="shadow-lg w-full rounded-xl overflow-hidden cursor-pointer"
>
<img src={blog.coverImage} alt="" />
<div class="p-7 flex flex-col gap-3">
<span class="text-purple-500 font-[500]">{blog.type}</span>
<h2 class="font-bold">{blog.title}</h2>
<span class="text-sm">{blog.content}</span>
</div>
</div>
);
}
Conclusion
Astro is a new and dynamic web development tool that allows us to use different frameworks under a single roof, and it has gained popularity among developers. Altogic, as a backend as a service platform, can be easily implemented in Astro just like in other frameworks and programming languages. This tutorial has provided us with the necessary knowledge to use Altogic comfortably in Astro.