| src | ||
| .env.example | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Moxie Backend
Express.js backend API for user management of an AI site, built with ESM syntax, Auth0 authentication, and SQLite database.
Features
- Auth0 Authentication: Secure authentication via Auth0
- User Management: Auto-creation of users on first login, profile management
- Credit System: Track and manage user credits
- API Keys: Generate and manage API keys for programmatic access
- Payment Webhooks: Ready for Stripe and PayPal integration
- Admin Endpoints: User management for administrators
- SQLite Database: Lightweight, file-based storage
Quick Start
# Install dependencies
npm install
# Copy environment file and configure
cp .env.example .env
# Edit .env with your Auth0 credentials
# Start the server
npm start
# Start in development mode (with auto-reload)
npm run dev
The server runs on port 9991 by default.
Auth0 Setup
1. Create Auth0 Application
- Go to Auth0 Dashboard > Applications > Applications
- Create a new "Single Page Application" or "Regular Web Application"
- Configure the following URLs:
- Allowed Callback URLs:
https://moxiegen.client.guacamolebox.net/api/callback - Allowed Logout URLs:
https://moxiegen.client.guacamolebox.net - Allowed Web Origins:
https://moxiegen.client.guacamolebox.net - Application Login URI:
https://moxiegen.client.guacamolebox.net/login
- Allowed Callback URLs:
2. Create Auth0 API (Optional)
For machine-to-machine authentication:
- Go to Auth0 Dashboard > Applications > APIs
- Create a new API
- Set the identifier as your audience
- Enable RBAC if needed
3. Configure Environment Variables
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
AUTH0_AUDIENCE=https://your-tenant.auth0.com/api/v2/
APP_URL=https://moxiegen.client.guacamolebox.net
API Endpoints
Auth Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/login |
Redirect to Auth0 login |
| GET | /api/callback |
Handle Auth0 callback |
| GET | /api/logout |
Logout and redirect |
User Endpoints (Requires Auth0 Token)
All authenticated endpoints require Authorization: Bearer <access_token> header.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/users/me |
Get current user profile |
| PUT | /api/users/me |
Update profile |
| DELETE | /api/users/me |
Deactivate account |
| GET | /api/users/credits |
Get credits and history |
| GET | /api/users/api-keys |
List API keys |
| POST | /api/users/api-keys |
Create new API key |
| DELETE | /api/users/api-keys/:keyId |
Revoke API key |
Admin Endpoints (Requires role: 'admin')
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/users |
List all users |
| GET | /api/users/:userId |
Get user by ID |
| PUT | /api/users/:userId |
Update user |
| DELETE | /api/users/:userId |
Delete user |
| POST | /api/users/:userId/credits |
Adjust user credits |
| PUT | /api/users/:userId/role |
Change user role |
Webhook Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/webhooks/stripe |
Stripe webhook handler |
| POST | /api/webhooks/paypal |
PayPal webhook handler |
Frontend Integration
Login Flow
// Redirect to Auth0 login
window.location.href = '/api/login';
// Handle callback (tokens in URL params)
const urlParams = new URLSearchParams(window.location.search);
const accessToken = urlParams.get('access_token');
const idToken = urlParams.get('id_token');
// Store token and use for API calls
localStorage.setItem('access_token', accessToken);
// Make authenticated requests
fetch('/api/users/me', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
Using Auth0 SPA SDK
import { Auth0Client } from '@auth0/auth0-spa-js';
const auth0 = new Auth0Client({
domain: 'your-tenant.auth0.com',
client_id: 'your-client-id',
redirect_uri: window.location.origin
});
// Login
await auth0.loginWithRedirect();
// Get token
const token = await auth0.getTokenSilently();
// Use token
fetch('/api/users/me', {
headers: {
'Authorization': `Bearer ${token}`
}
});
Database Schema
Users Table
id- Primary key (UUID)auth0_id- Auth0 user ID (sub claim)email- Email addressname- Display namepicture- Profile picture URLrole- User role ('user' or 'admin')credits- Available creditssubscription_status- Subscription statesubscription_tier- Subscription levelstripe_customer_id- Stripe customer referencepaypal_customer_id- PayPal customer referenceis_active- Account status flag
API Keys Table
id- Key IDuser_id- Foreign key to userskey_hash- Hashed API keyname- Key name/descriptionis_active- Key status
Credit Transactions Table
id- Transaction IDuser_id- Foreign key to usersamount- Credit amount (+/-)type- 'credit' or 'debit'description- Transaction description
Payments Table
id- Payment IDuser_id- Foreign key to usersamount- Payment amountprovider- 'stripe' or 'paypal'status- Payment status
Caddy Configuration
moxiegen.client.guacamolebox.net {
# Static site
root * /path/to/static/site
file_server
# API proxy
handle /api/* {
reverse_proxy localhost:9991
}
}
Making a User Admin
To promote a user to admin role:
- Find the user ID from the database
- Use the admin API (requires an existing admin)
- Or directly update the database:
UPDATE users SET role = 'admin' WHERE email = 'admin@example.com';
Payment Integration
Stripe Setup
- Create a Stripe account and get API keys
- Add keys to environment variables
- Create a webhook endpoint in Stripe dashboard pointing to
https://moxiegen.client.guacamolebox.net/api/webhooks/stripe - Copy the webhook signing secret to
STRIPE_WEBHOOK_SECRET
PayPal Setup
- Create a PayPal Developer account
- Create a REST API application
- Add credentials to environment variables
- Configure webhook in PayPal dashboard pointing to
https://moxiegen.client.guacamolebox.net/api/webhooks/paypal
Email Configuration (Contact Form)
Contact form submissions are automatically emailed to a configured address using Nodemailer with SMTP.
Setup
Add the following to your .env file:
# SMTP Email Configuration
SMTP_HOST=smtp.gmail.com # Your SMTP server
SMTP_PORT=587 # Usually 587 (TLS) or 465 (SSL)
SMTP_USER=your-email@gmail.com # Email address to send from
SMTP_PASS=your-app-password # Password or app-specific password
SMTP_SECURE=false # true for port 465, false for 587
SMTP_FROM=Moxie <your-email@gmail.com> # From display name & address
# Where contact form emails are sent (defaults to SMTP_USER)
CONTACT_EMAIL=notifications@yourdomain.com
Gmail Users
If you use Gmail, you must generate an App Password because regular passwords no longer work with SMTP:
- Go to Google Account Security
- Enable 2-Step Verification (if not already enabled)
- Go to App passwords (search in security settings)
- Create a new app password for "Mail"
- Use that 16-character password as
SMTP_PASS
Other Providers
| Provider | SMTP_HOST | SMTP_PORT | Notes |
|---|---|---|---|
| Gmail | smtp.gmail.com | 587 | Requires App Password |
| Outlook / Office 365 | smtp.office365.com | 587 | |
| SendGrid | smtp.sendgrid.net | 587 | Use API key as password |
| Mailgun | smtp.mailgun.org | 587 | |
| AWS SES | email-smtp.[region].amazonaws.com | 587 | Use SMTP credentials |
How It Works
When someone submits the contact form (POST /api/contact):
- The submission is saved to the database (always succeeds)
- An email notification is sent in the background (fire-and-forget)
- If email sending fails, the form still saves — a warning is logged but the user is not affected
The email includes:
- Plain-text and HTML versions
- The submitter's name, email, and company (if provided)
- The full message
- A reply-to header so you can reply directly to the submitter
License
ISC