Builder Docs

Everything you need to build your app on the Hasanat platform

Start from Scratch

Start your project in under 5 minutes using the starter template — pre-configured with Astro 5 + React 19 + Tailwind CSS v4 + Cloudflare D1.

1 Clone the template

git clone https://github.com/hasanat-dev/starter my-app
cd my-app && npm install
cp .env.example .env

2 Start developing

npm run dev
# → http://localhost:4321

3 Configure environment

# .env
AUTH_URL=https://auth.hasanat.dev
DB=hasanat-my-app-db

4 Submit your app

When ready, submit at hasanat.dev/apps — you'll get a subdomain and gallery listing.

↓ The sections below (Auth, Database, i18n...) apply to this path.

I Already Have an App

Have an Islamic app and want to list it on Hasanat? Welcome — you don't need to change anything in your code.

1 Submit Your App

Go to hasanat.dev/apps and click the add button. Enter your app's name, URL, and description in Arabic and English.

2 Get a Subdomain

Pick a subdomain like myapp.hasanat.dev — we'll point it to your existing site. Your app stays on your own hosting.

3 Optional: Integrate Shared Auth

If you want your users to use the same Hasanat account, you can integrate auth.hasanat.dev. See the Authentication section below.

Using an App Builder

You don't need to write code to build on Hasanat. Use any tool you like, then submit your app:

Full IDE in the browser — build and deploy instantly

Describe your app in words, get working code

Create full web apps from text descriptions

Design React interfaces using AI

Steps

  1. 1 Build your app using any of the tools above (or any other tool)
  2. 2 Deploy your app anywhere — Replit has built-in hosting, or use Vercel, Netlify, or any platform
  3. 3 Submit your app at hasanat.dev/apps — choose "External hosting" and enter your site URL
  4. 4 Get a .hasanat.dev subdomain pointing to your site
💡 Tip: App builders are great for simple projects. If you need advanced features (shared auth, D1 database), you can switch to the starter template later.

🔐 Authentication

auth.hasanat.dev provides unified authentication across all Hasanat apps. Supports Google and GitHub.

Shared Cookie Mode (Cloudflare Apps)

If your app is hosted on Cloudflare Pages under .hasanat.dev, the user signs in once and the cookie works automatically.

// src/middleware.ts
import { verifySession } from "./lib/auth";

export async function onRequest(context, next) {
const user = await verifySession(context.request);
context.locals.user = user; // null if not logged in
return next();
}

Access Current User

// In any .astro page or API route
const user = (Astro.locals as any).user;

if (user) {
console.log(user.id); // unique user ID
console.log(user.name); // display name
console.log(user.email); // email
console.log(user.image); // avatar URL
}

Protected Routes

// src/pages/api/my-data.ts
export const GET: APIRoute = async ({ locals }) => {
const user = (locals as any).user;
if (!user) return new Response("Unauthorized", { status: 401 });

// user is authenticated, proceed...
};

Login Button

<!-- Redirect to auth.hasanat.dev -->
<a href="https://auth.hasanat.dev/api/auth/signin">
Sign In
</a>

🗄️ Database

Cloudflare D1 — SQLite at the edge. Fast, free, and ready to use.

Basic Usage

// Access D1 binding
import { env } from "cloudflare:workers";
const db = env.DB;

// Query
const { results } = await db
.prepare("SELECT * FROM items WHERE user_id = ?")
.bind(userId)
.all();

// Insert
await db
.prepare("INSERT INTO items (name, user_id) VALUES (?, ?)")
.bind(name, userId)
.run();

Schema Conventions

CREATE TABLE items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name_ar TEXT NOT NULL, -- Arabic name
name_en TEXT, -- English (optional)
user_id TEXT, -- from auth session
status TEXT DEFAULT 'active',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Use bilingual columns (name_ar + name_en) for any user-facing text.

Migrations

# Create a migration
npx wrangler d1 migrations create my-db add-items

# Apply locally
npx wrangler d1 migrations apply my-db --local

# Apply to production
npx wrangler d1 migrations apply my-db --remote

🌍 i18n & RTL

Hasanat supports Arabic (default) and English. All user-facing text must be translated.

Translation Files

src/i18n/
├── ar.json # Arabic translations
├── en.json # English translations
└── utils.ts # useTranslations(), getLocalizedPath()

Using Translations

// In .astro files
import { useTranslations } from "../i18n/utils";
const t = useTranslations(locale);

<h1>{t("page.title")}</h1>

Logical CSS for RTL

Use Tailwind logical properties instead of left/right to support both directions:

❌ Don't use ✅ Use instead
ml-4ms-4
mr-4me-4
pl-4ps-4
pr-4pe-4
left-0start-0
right-0end-0
text-lefttext-start

☁️ Deployment

Deploy your app for free on Cloudflare Pages — or use any other hosting platform.

wrangler.toml

name = "my-hasanat-app"
compatibility_date = "2024-12-01"
pages_build_output_dir = "./dist"

[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "your-d1-id"

Deploy Commands

# Build
npm run build

# Deploy to Cloudflare Pages
npx wrangler pages deploy dist

# Or connect GitHub for auto-deploy
# Cloudflare Dashboard → Pages → Create → Connect to Git

Subdomain

After submitting your app through the apps page, you can request a subdomain like myapp.hasanat.dev. The Hasanat team reviews and sets it up for you.

Hosting Elsewhere?

You don't have to use Cloudflare. Submit your app through the apps page with your URL — you can get a .hasanat.dev subdomain pointing to your site.

🎨 Design System

The Hasanat visual identity: colors, fonts, and design principles.

Colors

hasanat-50

#f0fdfa

hasanat-100

#ccfbf1

hasanat-600

#0f766e

hasanat-700

#115e59

Colors are used via Tailwind CSS: bg-hasanat-600, text-hasanat-600, border-hasanat-200 etc.

Typography

Headings

font-display (Playfair Display)

Body text

System font stack (sans-serif)

Design Principles

  • Arabic-first, RTL by default
  • Islamic aesthetic: emerald/teal palette, respectful imagery
  • Clarity over decoration
  • Accessibility: focus states, contrast, screen readers
  • Full dark mode support