Ghost

Ghost ๐Ÿ‘ป: A headless identity and OTP authentication engine for Frappe. Centralizes Guest Sessions, Secure Login, and seamless Ghost-to-Real User conversion for building modern Web & Mobile apps.

Install Ghost

bench get-app https://github.com/muneeb141/ghost

Add the Frappe Gems badge to your README

Maintain Ghost? Paste this into your README:

[![Listed on Frappe Gems](https://frappegems.com/api/method/frappe_gems.seo.badge?app=muneeb141%2Fghost)](https://frappegems.com/gems/apps/muneeb141/ghost)

About Ghost

๐Ÿ‘ป Ghost

Let users browse anonymously, convert them when they're ready.

Stop losing customers at the signup wall. Ghost turns anonymous visitors into authenticated users without breaking their flow.

# Install
bench get-app https://github.com/muneeb141/ghost
bench --site your-site install-app ghost

License: MIT Frappe


โšก Quick Start (3 minutes)

  1. Create OAuth Client โ†’ Setup > Integrations > OAuth Client
  2. Enable Ghost โ†’ Setup > Ghost Settings โ†’ Paste Client ID
  3. Done! Test with curl:
curl -X POST http://your-site:8000/api/method/ghost.api.ghost.create_ghost_session

What you get back:

{
  "user": "ghost_abc123@guest.local",
  "access_token": "...",    // Use this to make authenticated requests
  "refresh_token": "...",   // Use this to get new access tokens
  "expires_in": 3600        // Token valid for 1 hour
}

๐ŸŽฏ What Problem Does This Solve?

Before Ghost: - User visits your site โ†’ Signup wall โ†’ 70% bounce - Mobile app โ†’ Complex login flow โ†’ User drops off - E-commerce โ†’ "Add to cart" requires account โ†’ Lost sale

After Ghost: 1. User arrives โ†’ Gets temporary "ghost" identity instantly 2. Browses, adds to cart, saves favorites โ†’ All tracked 3. Ready to checkout โ†’ Quick OTP โ†’ Becomes real user 4. All data preserved! Cart, favorites, browsing history

Perfect for: - ๐Ÿ›’ E-commerce (browse โ†’ cart โ†’ checkout โ†’ sign up) - ๐Ÿ“ฑ Mobile apps (explore โ†’ authenticate when needed) - ๐Ÿ“ฐ Content platforms (read โ†’ save โ†’ register) - ๐Ÿ’ผ SaaS (try features โ†’ upgrade โ†’ convert)


๐Ÿš€ How It Works

Anonymous User
      โ†“
Create Ghost Session  โ†’  Get Bearer Token
      โ†“
Browse, Add to Cart   โ†’  Authenticated as ghost_abc123@guest.local
      โ†“
Ready to Convert      โ†’  Send OTP to email
      โ†“
Enter OTP             โ†’  Convert to user@example.com
      โ†“
All cart data stays!  โ†’  New tokens for real user

Under the hood: - OAuth2 bearer tokens (industry standard, super secure) - No cookies needed (perfect for mobile/SPAs) - Tokens expire & refresh automatically - Fast split conversion path: - Rename path when real_email does not exist (ghost user is renamed) - Manual migration path when real_email already exists (app-owned ghost data is reassigned, no heavy framework User merge)


๐Ÿ“ฑ Frontend Integration (Copy-Paste Ready)

JavaScript/React/Vue

// 1. Create ghost on page load
const response = await fetch('/api/method/ghost.api.ghost.create_ghost_session', {
  method: 'POST'
});
const { access_token, refresh_token } = await response.json().message;
sessionStorage.setItem('token', access_token);

// 2. Make authenticated requests
fetch('/api/resource/Item', {
  headers: { 'Authorization': `Bearer ${sessionStorage.getItem('token')}` }
});

// 3. Convert when ready
// Send OTP
await fetch('/api/method/ghost.api.otp.send_otp', {
  method: 'POST',
  body: JSON.stringify({ email: 'user@example.com', purpose: 'Conversion' })
});

// Convert with OTP
await fetch('/api/method/ghost.api.ghost.convert_to_real_user', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    ghost_email: 'ghost_xxx@guest.local',
    real_email: 'user@example.com',
    otp_code: '123456'
  })
});
// โœจ User converted! All data preserved!

๐ŸŽฎ Test It Out

We've included a Bruno collection with ready-to-run API tests:

# Open apps/ghost/bruno/ in Bruno
# Run tests in order:
1. Create Ghost Session  โœ“
2. Refresh Token         โœ“
3. Send OTP              โœ“
4. Convert to Real User  โœ“

Full testing guide โ†’


โš™๏ธ Configuration (The Important Bits)

Ghost Settings (Setup > Ghost Settings):

Setting What It Does Default
Client ID OAuth client (required!) -
Access Token Expiry How long before re-auth 1 hour
Invalidate on Conversion Revoke ghost tokens when converting โœ“
Verify OTP on Conversion Require email verification โœ“

That's it! Everything else has smart defaults.


๐Ÿ” Security (Yes, It's Production-Ready)

โœ… OAuth2 bearer tokens (same as Google/Facebook)
โœ… Short-lived access tokens (1 hour, configurable)
โœ… Token refresh without re-login
โœ… Automatic token revocation on conversion
โœ… Rate limiting on all endpoints
โœ… HTTPS support (required in production)

Mobile apps? Works perfectly (no cookies needed).


๐Ÿ“š Full Documentation

Too much info above? โ†’ Full README โ†’
Need API reference? โ†’ Bruno tests โ†’
Want examples? โ†’ See Frontend Integration above โ†‘


๐Ÿค” Common Questions

Q: Do I need to handle token refresh myself?
A: Yes, but it's one API call. Just call /refresh_bearer_token before expiry.

Q: What happens to ghost user's cart when they convert?
A: Conversion preserves app-owned ghost data. New emails use rename conversion; existing emails use explicit app-level migration without generic User merge.

Q: Can I use this in production?
A: Yes! OAuth2 tokens are industry-standard. Used in real ecommerce sites.

Q: Mobile app support?
A: Perfect for mobile. No cookies, just tokens. Works on iOS/Android.

Q: Is it GDPR compliant?
A: Yes. Ghost users auto-delete after expiry. Full data control.


๐Ÿ› ๏ธ Troubleshooting

"OAuth Client ID is required"
โ†’ Create OAuth Client (Setup > Integrations), copy ID to Ghost Settings

"Invalid token"
โ†’ Token expired (1 hour). Call /refresh_bearer_token with refresh token.

"OTP Code required"
โ†’ Send OTP first: /send_otp, then include code in conversion request.


๐Ÿ“Š What You Get

โœ… Instant anonymous user sessions
โœ… OAuth2 bearer token authentication
โœ… OTP verification (email/SMS)
โœ… Seamless ghost โ†’ real user conversion
โœ… All data preserved on conversion
โœ… Token refresh for seamless UX
โœ… Auto-cleanup of expired ghosts
โœ… Rate limiting & security
โœ… Mobile-friendly (no cookies)
โœ… Production-ready


๐Ÿค Contributing

PRs welcome!

Quick start:

git clone https://github.com/muneeb141/ghost
cd ghost
# Make changes, run tests
bench --site dev run-tests --app ghost

๐Ÿ“œ License

MIT License - Use it however you want!


๐Ÿ’ฌ Support


Made with โค๏ธ for the Frappe community

Stop losing users at the signup wall. Try Ghost today!

Related Other apps for Frappe & ERPNext

  • Erpnext โ€” Free and Open Source Enterprise Resource Planning (ERP)
  • Helpdesk โ€” Modern, Streamlined, Free and Open Source Customer Service Software
  • Print Designer โ€” Visual print designer for Frappe / ERPNext
  • Ctr โ€” CTRๆจกๅž‹ไปฃ็ ๅ’Œๅญฆไน ็ฌ”่ฎฐๆ€ป็ป“
  • Whitelabel โ€” Whitelabel ERPNext
  • Fossunited โ€” fossunited.org
  • Helm โ€” Helm Chart Repository for Frappe/ERPNext
  • Frappe Attachments S3 โ€” A frappe app to upload file attachments in doctypes to s3.