Skip to content

Build from the starter

The Hasanat starter is the suggested starting point for new apps. It is a public, MIT-licensed repository set up for Arabic first and for Cloudflare.

  • Astro 5 with server rendering, and React 19 for interactive parts.
  • Tailwind CSS v4 and strict TypeScript.
  • Arabic (RTL, the default) and English.
  • Ready-made integration with shared sign-in.
  • Helpers for a Cloudflare D1 database and a setup for Cloudflare Pages.
  • Biome for formatting and linting, zod for input validation, and lucide-react for icons.
  • Four coding-agent skills in .github/skills/. These copies are older than the skills pack; use the pack.

git, Node.js 20 or newer, and npm. The starter uses npm and package-lock.json; do not switch package managers.

  1. Create your copy. Press Use this template on the starter’s GitHub page to create your repository, or clone it directly:

    نافذة طرفيّة
    git clone --depth 1 https://github.com/hasanat-dev/starter.git my-app
    cd my-app
  2. Install dependencies and copy the environment file:

    نافذة طرفيّة
    npm install
    cp .env.example .env
  3. Start the development server:

    نافذة طرفيّة
    npm run dev

    Open the URL Astro prints, normally http://localhost:4321. The root redirects to /ar/. If the port is busy, use the URL Astro picks instead of stopping another process.

  4. Check the build before you change anything:

    نافذة طرفيّة
    npm run check
    npm run build

The first success checkpoint is a real page running on your machine. Sign-in, a database, and deployment are later, optional steps.

We tried the starter unchanged on 13 October 2026: install, build, and the development server work, but two commands fail.

  • npm run check reports one error: Cannot find name 'D1Result' in src/lib/db.ts. Add this line to src/env.d.ts, next to the D1Database type:

    type D1Result = import("@cloudflare/workers-types").D1Result;
  • npm run lint stops because biome.json uses Biome 1 keys while the starter installs Biome 2. npx biome migrate --write updates the configuration, but some rules still flag Astro files and Tailwind syntax. Rely on npm run check and npm run build until the starter is fixed.

  • .env.example has only two variables: PUBLIC_SITE_URL and PUBLIC_APP_NAME. Shared sign-in needs no secrets.
  • Two commented lines, HASANAT_CLIENT_ID and HASANAT_CLIENT_SECRET, refer to an OAuth flow for external apps. That flow does not exist today, so leave them as they are. See sign-in.
  • Never commit secrets or send them in a chat or a request.
src/
├── middleware.ts reads the sign-in session
├── lib/
│ ├── auth.ts sign-in and sign-out links, protected pages
│ └── db.ts D1 helpers
├── layouts/
│ └── Layout.astro sets lang and dir
├── pages/
│ ├── index.astro redirects to /ar/
│ ├── ar/ Arabic pages
│ ├── en/ English pages
│ └── api/health.ts
├── i18n/ ar.json, en.json, utils.ts
└── styles/global.css Tailwind colours and fonts
schema.sql database schema
wrangler.toml Cloudflare settings
.env.example
.github/skills/ coding-agent skills
AGENTS.md instructions for coding agents
DATA_POLICY.md data policy for builders
Command What it does
npm run dev Starts the development server at localhost:4321
npm run build Builds for production
npm run preview Previews the build locally
npm run lint Lints with Biome
npm run check Runs TypeScript and Astro checks
npm run db:migrate:local Applies schema.sql to the local D1 database
npm run db:migrate:prod Applies it to the production database

Before the database commands, replace YOUR_DB_NAME in package.json with your database name.

From the starter’s AGENTS.md:

  • Import with the @/ path alias.
  • Use Tailwind logical properties such as ms-* and pe-* instead of ml-* and pr-*.
  • Add every user-facing string to both ar.json and en.json; do not hardcode text in pages.
  • Biome for formatting, not Prettier; zod for input validation; lucide-react for icons.
  • Do not add Firebase or another auth provider: use auth.hasanat.dev and D1.
  • Shape the first version around one useful outcome, following the spec if it is a Hasanat project.
  • When you need sign-in, a database, or a subdomain, read shared services (in Arabic).
  • The starter’s README points to an old submission page on hasanat.dev that is no longer the way to work. Request subdomains and listings from the platform dashboard.