@ma7moudsalama/falak-app

Production-ready Vue 3 boilerplate with Firebase, PrimeVue, Tailwind, i18n, Groq AI, Paymob & more
1,381
Install
npm install @ma7moudsalama/falak-app
Latest Version:1.0.2
License:MIT
Last Updated:Apr 4, 2026
Links: GitHub  ·  npm
Maintainer: ma7moudsalamacoder

فَلَك · Falak App

Production-ready Vue 3 boilerplate with Firebase, PrimeVue, Tailwind CSS, i18n (Arabic + English), Groq AI, Paymob payments, offline IndexedDB sync, and AES encryption — all wired up and ready to build on.

npm version License: MIT


Quick Start

# Scaffold a new project
npx @ma7moudsalama/falak-app create my-project

# Or install globally
npm i -g @ma7moudsalama/falak-app
falak create my-project

# Then
cd my-project
cp .env.example .env     # fill in your keys
npm run dev

What's Inside

Layer Package Status
Framework Vue 3 + Vite ✅ Configured
UI Library PrimeVue 4 (Aura theme) ✅ Configured
Styling Tailwind CSS 3 ✅ Configured
State Pinia ✅ Configured
Routing Vue Router 4 ✅ Configured + guards
Translation Vue I18n 10 (EN + AR/RTL) ✅ Configured
Auth Firebase Auth (Email, Google, Facebook) ✅ Composable ready
Database Firebase Realtime DB ✅ Composable ready
Offline IndexedDB via idb ✅ Auto-sync
Encryption AES-256 via crypto-js ✅ Composable ready
AI Groq SDK (LLaMA 3.3) ✅ Composable ready
Payments Paymob ✅ Composable + subscriptions

Project Structure

src/
├── assets/
│   └── main.css              ← Tailwind + custom utilities
├── components/
│   └── layout/
│       └── AppLayout.vue     ← Sidebar + topbar layout shell
├── composables/
│   ├── useAuth.js            ← Firebase auth + roles + sessions
│   ├── useDatabase.js        ← RTDB + IndexedDB offline manager
│   ├── useCrypto.js          ← AES encrypt/decrypt
│   ├── useGroq.js            ← Groq AI chat + streaming
│   └── usePaymob.js          ← Paymob payments + subscriptions
├── firebase/
│   └── index.js              ← Firebase app init + all services
├── i18n/
│   ├── index.js              ← Vue I18n setup + locale switcher
│   └── locales/
│       ├── en.json
│       └── ar.json
├── router/
│   └── index.js              ← Routes + auth/role guards
├── stores/
│   └── auth.js               ← Pinia wrapper for useAuth
├── views/
│   ├── auth/
│   │   ├── LoginView.vue
│   │   ├── RegisterView.vue
│   │   └── ForgotView.vue
│   ├── HomeView.vue
│   ├── DashboardView.vue     ← Live data + AI + subscription demo
│   ├── ProfileView.vue
│   ├── AdminView.vue
│   └── NotFoundView.vue
├── App.vue
└── main.js

Configuration

1. Firebase

Edit src/firebase/index.js or set your .env:

VITE_FIREBASE_API_KEY=...
VITE_FIREBASE_AUTH_DOMAIN=...
VITE_FIREBASE_DATABASE_URL=...
VITE_FIREBASE_PROJECT_ID=...
VITE_FIREBASE_STORAGE_BUCKET=...
VITE_FIREBASE_MESSAGING_SENDER_ID=...
VITE_FIREBASE_APP_ID=...

Enable in Firebase Console:

  • Authentication → Email/Password, Google, Facebook
  • Realtime Database → create database
  • Upload firebase-rules.json as your security rules

2. Groq AI

VITE_GROQ_API_KEY=gsk_...
VITE_GROQ_MODEL=llama-3.3-70b-versatile

Get your key at console.groq.com.

3. Paymob

VITE_PAYMOB_API_KEY=...
VITE_PAYMOB_INTEGRATION_ID=...
VITE_PAYMOB_IFRAME_ID=...
VITE_PAYMOB_HMAC_SECRET=...

Get credentials from accept.paymob.com.

4. Encryption

VITE_ENCRYPTION_KEY=your_strong_random_secret

Composables API

useAuth()

import { useAuth } from '@/composables/useAuth.js'

const {
  currentUser,      // Ref<FirebaseUser | null>
  userProfile,      // Ref<Object>        — RTDB profile
  userRole,         // Ref<string>        — live from RTDB
  isAuthenticated,  // ComputedRef<bool>
  isAdmin,          // ComputedRef<bool>
  isSuperAdmin,     // ComputedRef<bool>
  isAuthReady,      // Ref<bool>          — true after first auth check
  isLoading,        // Ref<bool>
  authError,        // Ref<string | null>

  register,         // ({ email, password, displayName }) → { success, user }
  login,            // ({ email, password })              → { success, user }
  logout,           //                                    → { success }
  resetPassword,    // (email)                            → { success }
  changePassword,   // ({ currentPassword, newPassword }) → { success }
  loginWithGoogle,  // (useRedirect?)                     → { success, user }
  loginWithFacebook,// (useRedirect?)                     → { success, user }
  updateUserProfile,// (data)                             → { success }
  setUserRole,      // (uid, role)                        → { success }   ← admin only
  deleteAccount,    //                                    → { success }
  hasPermission,    // (permission) → bool
  hasRole,          // (...roles)   → bool
  ROLES             // { SUPER_ADMIN, ADMIN, USER, GUEST }
} = useAuth()

User roles are stored in /users/{uid}/role in RTDB and listened to in real-time. Session data (online, lastSeen) is written to /sessions/{uid} with onDisconnect handling.


useDatabase(options?)

import { useDatabase } from '@/composables/useDatabase.js'

const db = useDatabase({
  encryptedPaths: ['payments/*'],   // paths to auto-encrypt
  encryptFields:  ['ssn', 'card']   // field names to encrypt
})

// One-time read (offline-aware)
const user = await db.get('users/uid123')

// Write (blocked offline with error)
await db.set('todos/1', { text: 'Buy milk', done: false })
await db.update('todos/1', { done: true })
await db.push('todos', { text: 'New item' })   // → { success, key }
await db.remove('todos/1')

// Real-time listener (reactive ref + IDB sync)
const { data, unsubscribe } = db.listen('todos')
// data.value updates live

// Real-time child events (efficient for large lists)
const { items, unsubscribe } = db.listenList('messages')
// items.value = { key1: {...}, key2: {...} }

// Offline-only reads
const cached = await db.getOffline('todos')
const all    = await db.getAllOffline('todos')

// Network status
db.isOnline   // Ref<bool>

Offline behavior:

  • All write operations return { success: false, error: 'You are offline. Data is read-only.' } when offline.
  • Read operations return IndexedDB cached data.
  • Remote changes are auto-synced to IDB when online.

useCrypto()

import { useCrypto } from '@/composables/useCrypto.js'

const { encrypt, decrypt, encryptObject, decryptObject,
        encryptFields, decryptFields, hash, hmac, randomToken } = useCrypto()

const cipher = encrypt('sensitive data')
const plain  = decrypt(cipher)

const encObj = encryptObject({ ssn: '123-45-6789', name: 'Max' })
const obj    = decryptObject(encObj)

// Encrypt only specific fields
const safe = encryptFields(userData, ['ssn', 'bankAccount'])
const back = decryptFields(safe, ['ssn', 'bankAccount'])

// SHA256 hash
const hashed = hash('mypassword')

// HMAC (used by Paymob webhook verification)
const sig = hmac('message', 'secret')

useGroq(systemPrompt?)

import { useGroq } from '@/composables/useGroq.js'

const groq = useGroq('You are a helpful assistant.')

// Single prompt
const reply = await groq.chat('What is Vue.js?')

// Streaming
await groq.streamChat('Tell me a story', (chunk, full) => {
  output.value = full
})

// Multi-turn conversation
await groq.sendConversation('Hello!')
await groq.sendConversation('What did I just say?')

// Streaming multi-turn
await groq.streamConversation('Continue...', (chunk) => { ... })

// Audio transcription (Whisper)
const text = await groq.transcribe(audioBlob, 'ar')

groq.clearConversation()
groq.setSystemPrompt('New system prompt')

usePaymob() + useSubscription()

import { usePaymob, useSubscription, PLANS } from '@/composables/usePaymob.js'

// ── Payments ──
const paymob = usePaymob()

// Full payment flow → opens iframe URL
const result = await paymob.initPayment({
  amountCents: 14900,       // 149.00 EGP
  currency:    'EGP',
  billingData: { ... }
})
// result.iframeUrl  → embed or open

// Open in new tab
await paymob.openPaymentTab({ amountCents: 14900, ... })

// Verify Paymob webhook HMAC
const valid = paymob.verifyHmac(callbackData)

// ── Subscriptions ──
const sub = useSubscription()

// Initialize free plan for new users
await sub.initFreeplan(userId)

// Activate after successful payment
await sub.activateSubscription(userId, 'PRO', { paymobOrderId: 12345, amountCents: 14900 })

// Real-time subscription listener
const { data } = sub.listenSubscription(userId)
// data.value = { planId, status, expiresAt, features, ... }

// Feature gating
const canUseAPI = await sub.hasFeature(userId, 'api_access')
const active    = await sub.isActive(userId)

await sub.cancelSubscription(userId)

Subscription data in RTDB (/subscriptions/{uid}):

{
  "planId":    "pro",
  "planName":  "Pro",
  "status":    "active",
  "features":  ["read", "write", "advanced_features", "api_access"],
  "startedAt": 1700000000000,
  "expiresAt": 1702592000000,
  "autoRenew": true,
  "paymentHistory": [{ "paidAt": 1700000000000, "amountCents": 14900 }]
}

i18n

import { setLocale } from '@/i18n/index.js'

setLocale('ar')   // switches to Arabic + sets dir="rtl"
setLocale('en')   // switches to English + sets dir="ltr"

In templates:

<p>{{ $t('auth.email') }}</p>
<p>{{ $d(date, 'short') }}</p>
<p>{{ $n(149, 'egp') }}</p>

To add a new language, add its locale file to src/i18n/locales/ and register it in src/i18n/index.js.


Security Rules

Upload firebase-rules.json to your Firebase Realtime Database rules:

Firebase Console → Realtime Database → Rules → paste contents

Scripts

npm run dev       # Start dev server (http://localhost:5173)
npm run build     # Production build → dist/
npm run preview   # Preview production build
npm run lint      # Lint + auto-fix

License

MIT © Falak App

Related Packages

battlestack

Battlestack — plugin-based scaffolding CLI for Nuxt 4. This unscoped package is...

938 3
@battlestack/cli

Battlestack CLI engine — open-source scaffolding tool. Loads extra capabilities...

918 3
create-prism-app

Scaffold a production-grade, opinionated full-stack starter in seconds — Vue, Nu...

970 0
upvue

Vue toolkit of plugins to bootstrap your VueApp with everything you need

1,901
@nuxtus/nuxtus

Directus/Nuxt boilerplate with Tailwind CSS.

1,882 90

Version History

Version Released License
1.0.2 MIT
1.0.1 MIT
1.0.0 MIT