Getting Started
DUXMNG is a platform to publish and distribute software, scripts, bots and other digital products.
- Create an account on
register.html(Google or Discord). - Sign in on
login.html. - Publish a product on
upload.html(login required). - Browse products on
explore.html(public, no login needed).
Architecture
The frontend uses Supabase for authentication, database and storage.
Public configuration lives in assets/config.js
and application logic in assets/app.js.
Browser
|
|-- HTML pages
|-- assets/style.css
|-- assets/app.js
|
v
Supabase
|-- Auth (Google, Discord)
|-- Postgres (profiles, products, messages)
|-- Storage (products bucket private, media bucket public)
Authentication
Frontend authentication uses Supabase Auth with Google and Discord only. Protected actions (publishing, messaging, editing your profile) require a session.
Google / Discord login
await supabase.auth.signInWithOAuth({
provider: 'google', // or 'discord'
options: { redirectTo: 'https://your-site.com/upload.html' }
});
Both providers must be enabled in Supabase under
Authentication - Providers, with the callback URL
https://YOUR-PROJECT.supabase.co/auth/v1/callback.
New users get their profile row (username + avatar) created
automatically on first sign in.
Session
const { data: { session } } =
await supabase.auth.getSession();
Products
The products table holds published software metadata.
Price 0 means free (direct download).
Price above 0 means paid (private contact only).
List products
const { data } = await supabase
.from('products')
.select('id,title,slug,description,category,price,downloads,cover_image_url')
.eq('status', 'published')
.order('created_at', { ascending: false });
Create product (login required)
const { error } = await supabase.from('products').insert({
creator_id: user.id,
title, slug, description, category,
price, cover_image_url, gallery_urls,
video_url, file_url, status: 'published'
});
Upload
Images and free product files go to the public
media bucket. Paid product files (optional) go to
the private products bucket.
Publish flow
1. Require an authenticated user (profile auto-created)
2. Upload cover + gallery photos to the public media bucket
3. Upload the product file (public bucket if free, private if paid)
4. Save the product row with status 'published'
5. Redirect to product.html?slug=...
Downloads
Free products expose a public file_url, so anyone
can download them with a normal link and no account.
Paid products have no public file: buyers contact the seller.
// free product
const a = document.createElement('a');
a.href = product.file_url;
a.download = '';
a.click();
Private messages
Buyers write to sellers through the Messages table.
Only sender and receiver can read each row (enforced by RLS).
await supabase.from('messages').insert({
product_id, sender_id: user.id,
receiver_id: product.creator_id, body
});
Profiles
Every account has a row in profiles with username,
avatar, bio and contact info. OAuth users (Google/Discord) get
their profile created automatically, with avatar imported.
Update profile
await supabase.from('profiles').upsert({
id: user.id,
username, bio,
discord_username, contact_email, avatar_url
});
Security
- Never expose a Supabase
service_rolekey in the frontend. - Use RLS for protected data.
- Keep paid product files in the private bucket.
- Validate files and input server-side before a public launch.
- Apply rate limiting to public endpoints.