|
Some checks failed
Docker Compose Pipeline / docker-check (push) Failing after 39s
|
||
|---|---|---|
| .cursor | ||
| .gitea/workflows | ||
| .vscode | ||
| docs | ||
| Documents | ||
| fyp-docs | ||
| prisma | ||
| public | ||
| scripts | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| .npmrc | ||
| .tmp_supplier_cookies.txt | ||
| docker-compose.dev.yml | ||
| docker-compose.ec2.yml | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| eslint.config.mjs | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| pnpm-lock.yaml | ||
| postcss.config.mjs | ||
| prisma.config.ts | ||
| README.md | ||
| saad.commands | ||
| tsconfig.json | ||
| vitest.config.ts | ||
JUNO
🚀 Modern commerce & AI‑powered support infrastructure for Shopify based dropshipping businesses.
Tech stack
JUNO is a full‑stack Next.js application that powers:
- A Vendor Portal for Shopify merchants
- A Supplier Portal for product providers
- An Admin view for operations
- An AI‑powered helpdesk and knowledge engine called JUNOCHAT / Juno Engine
Everything runs inside a single Next.js App Router project (frontend + backend + background jobs). 💻
📚 Table of Contents
- High‑Level Overview
- Core Features
- Architecture & Tech Stack
- Problems & Solutions
- Future Enhancements
- Local Development
- Docker & Deployment
- OpenAI, Groq & AI Setup
- Prisma & Database
- License
🧭 High‑Level Overview
JUNO centralizes communication and operations between vendors (Shopify stores) and suppliers:
-
Vendors can:
- Connect Shopify stores and sync products.
- Receive products and price offers from suppliers.
- See new products in a clean, auto‑refreshing New Products view.
- Get notifications when suppliers change prices or withdraw products.
-
Suppliers can:
- Manage their product catalog with images and pricing.
- Accept product sync requests from vendors.
- Provide products and custom pricing per vendor.
- Edit synced product price/quantity per vendor with inline controls.
-
Both sides are supported by:
- JUNOCHAT – an AI assistant powered by OpenAI (embeddings + chat where configured) and Groq (fast chat for storefront widget, Gmail flows, and KB fallback) that can answer questions using the knowledge base, FAQs, and store context.
- A Juno Engine area for Gmail and ticketing workflows.
✨ Core Features
🛍️ Vendor Portal
-
Shopify connections
- Connect one or more Shopify stores to JUNO.
- Webhooks keep orders, inventory, and products in sync.
-
New Products
- Consolidated list of:
- Products vendors requested and had synced by suppliers.
- Products provided directly by suppliers via offers.
- Clean row‑based layout (no heavy cards) that:
- Auto‑refreshes in the background on an interval and when the tab becomes visible.
- Avoids UI flicker by only updating when data actually changes.
- Product detail sheet with:
- Price
- Supplier
- Optional quantity/amount
- Description and image
- Clicking outside the detail closes it (no need to aim at a tiny “X”).
- Consolidated list of:
-
Suppliers Directory
- Discover global suppliers.
- Send connection invitations.
- Track connection status (PENDING / CONNECTED / REJECTED).
-
Notifications
- Vendors are notified when:
- A supplier accepts a product sync request.
- A supplier provides a new product.
- A supplier updates the price or quantity of an offered/synced product.
- Vendors are notified when:
🤝 Supplier Portal
-
Vendor Connections
- Accept invitations using secure tokens.
- See all connected vendors with status filters.
- Accept / reject product sync requests from vendors with a dedicated panel.
-
Synced Products Per Vendor
- For each vendor, suppliers see a synced products block:
- Compact, scrollable list for large catalogs.
- Shows image, title, SKU, description.
- Inline edit controls for:
- Price (for that vendor)
- Available amount / quantity (for that vendor)
- Updates flow through
ProductSyncso the vendor’s New Products view reflects the new price/amount.
- For each vendor, suppliers see a synced products block:
-
Provided Products (Offers)
- Suppliers can:
- Select products from their catalog.
- Specify per‑vendor price and total quantity.
- See all offers in a tidy list with image, SKU, and timestamps.
- Edit offer:
- Opens a modal (no page jump) to change price and quantity.
- Sends a notification to the vendor about the update.
- Withdraw offer:
- Opens a custom confirmation dialog:
- “You are about to withdraw {productName} from {vendorName}…”
- On confirm, removes the offer and the product disappears from the vendor’s New Products list.
- Opens a custom confirmation dialog:
- Suppliers can:
-
Products Catalog
- Manage own products (create/update/delete).
- Upload images via:
- S3 in hosted environments, or
- Local
public/uploadsin pure local dev.
- Safeguards:
- Synced products from vendors are editable but not deletable.
- UI labels clarify when a product is “Synced” and where it came from.
🛠️ Admin / Ops
-
Admin page with an overview of:
- Stores
- Vendors
- Suppliers
- Juno Engine activity
-
Email‑centric ops:
- Gmail polling and webhook endpoints.
- Email logs and templates.
- MFA setup, notifications, and account hygiene flows.
🤖 JUNOCHAT (AI Helpdesk)
JUNOCHAT (a.k.a. Juno Engine chat) is the AI layer that:
- Uses OpenAI and Groq:
- OpenAI (
text-embedding-3-small, etc.) for knowledge‑base embeddings stored in Postgres/pgvector. - OpenAI (
gpt-4o-miniby default, configurable) for KB “Ask” answers whenOPENAI_API_KEYis set. - Groq for storefront widget replies, Gmail classification/safety/preview flows, and KB fallback if OpenAI chat fails.
- OpenAI (
- Supports:
- FAQ ingestion and retrieval.
- Knowledge document upload + chunking.
- RAG‑style responses for store‑specific questions (orders, products, policies, etc.).
- Integrates with the rest of JUNO:
- Can respond based on vendor/supplier context.
- Ties into the Juno Engine Gmail / ticketing workflow so AI can assist with replies.
Future Enhancements
Future Enhancements for JUNOCHAT & AI
-
Deeper Shopify awareness
- Let JUNOCHAT answer questions like:
- “Which supplier provides the top‑selling items in the last 30 days?”
- “What is the margin per vendor on synced products?”
- Let JUNOCHAT answer questions like:
-
Multi‑channel support
- Extend Juno Engine beyond Gmail:
- WhatsApp / SMS
- Messenger / Instagram DMs
- Shopify Inbox
- Extend Juno Engine beyond Gmail:
-
Active suggestion engine
- Use embeddings + usage data to:
- Suggest products suppliers should offer to specific vendors.
- Recommend pricing bands per market/region.
- Use embeddings + usage data to:
-
Self‑service playbooks
- Let admins define reusable “AI playbooks”, e.g.:
- “Handle delayed shipment” flow.
- “Out‑of‑stock product” flow.
- JUNOCHAT would follow these playbooks when generating replies.
- Let admins define reusable “AI playbooks”, e.g.:
Architecture & Tech Stack
- Framework: Next.js (App Router, TypeScript)
- UI: React + Tailwind‑style utility classes
- Auth: NextAuth
- Database: PostgreSQL via Prisma ORM
- Background / Integrations:
- Gmail APIs (OAuth)
- Shopify APIs (orders, products, inventory)
- OpenAI (embeddings + optional chat) and Groq (chat / classification)
- Deployment: Docker + GitHub Actions → AWS EC2
Problems & Solutions
1. Dropshipping is glued together with spreadsheets and chats 😵💫
Typical Shopify dropshipping today:
- Vendors discover suppliers in WhatsApp groups, email threads, or random marketplaces.
- Product info, pricing, and availability live in:
- Google Sheets
- Excel files
- Long chat histories and voice notes
- When something changes (price increases, product discontinued), it’s easy to miss and very hard to trace.
How JUNO helps:
- Formal connections between Shopify stores and suppliers.
- Structured models (
ProductSync,SupplierProductOffer) instead of ad‑hoc spreadsheets. - Every new product or change becomes:
- A record in the database.
- A visible entry in the New Products list.
- A notification to the affected party (vendor or supplier).
👉 Result: less “Did you see my message?” and more “The system already updated this.”
2. No single source of truth for cost, price, and margin per vendor 💸
In a typical Shopify setup:
- Supplier sends a Google Sheet with “latest prices”.
- Vendor copies that into Shopify, maybe with manual mark‑ups.
- If the supplier changes cost for one vendor, everyone else may still see old prices.
- Nobody is sure what the current agreed cost is for a given product/vendor pair.
How JUNO helps:
- Suppliers manage per‑vendor offers directly in the Supplier Portal:
- Price and quantity are editable inline.
- Synced products from vendors can be overridden per store.
- Vendors see the resulting price and available amount in one place:
- The New Products page, refreshed in the background.
- Notifications whenever suppliers change price/quantity.
👉 Result: vendors always see the latest cost per product per supplier, and suppliers stay in control of what each partner gets.
3. Operational noise across email, tickets, and knowledge 💬
Pain today:
- Support lives in Gmail, while operations live in Shopify, and documentation is buried in Notion/Docs.
- Agents manually copy/paste order IDs, tracking links, and policy snippets into replies.
- Repeated questions (“Where is my order?”, “What’s your return policy?”) steal time from real issues.
How JUNO helps:
- JUNOCHAT + Juno Engine:
- Ingest FAQs and internal docs into a vectorized knowledge base (via OpenAI embeddings).
- Answer questions using RAG against that knowledge.
- Integrate with Gmail so tickets and AI context live in the same place.
👉 Result: fewer repetitive replies, faster accurate responses, and a single surface for “what we know” + “what customers ask”.
Local Development
- Install dependencies
npm install
- Create
.env
Copy .env.example (or the variables listed below) into a local .env file and fill in your own values:
DATABASE_URLNEXTAUTH_SECRETNEXTAUTH_URLGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETSMTP_HOSTSMTP_PORTSMTP_SECURESMTP_USERSMTP_PASSWORDOPENAI_API_KEY(embeddings + KB chat; optionalOPENAI_CHAT_MODEL,OPENAI_EMBEDDING_MODEL,OPENAI_EMBEDDING_DIMENSIONS)GROQ_API_KEY(storefront chat, Gmail AI helpers, KB chat fallback; optionalGROQ_MODEL)AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_REGION(if you use S3 or other AWS services—not required for AI-only local dev)ADMIN_EMAILADMIN_PASSWORD
Never commit real secrets;
.env*files are ignored by git.
- Run the dev server
npm run dev
Visit http://localhost:3000 in your browser.
Docker & Deployment
The project can be run via Docker using the provided Dockerfile and docker-compose.yml.
Typical pattern:
docker compose up -d --build
Make sure your .env is present next to the app code so the container can read it.
CI/CD on AWS EC2
This repo includes a GitHub Actions workflow at .github/workflows/deploy-ec2.yml that:
- Runs on pushes to the
mainbranch. - Installs dependencies and builds the Next.js app.
- SSHes into an EC2 instance.
- Writes an
.envfile on the EC2 instance from a single GitHub secretEC2_ENV. - Uses
docker compose/docker-composeto build and run the app. - Performs a health check and automatically rolls back to the previous commit if the deployment or health check fails.
Required GitHub Secrets
Set the following secrets in GitHub → Settings → Secrets and variables → Actions:
EC2_HOST– public IP or DNS of the EC2 instance.EC2_USER– SSH user (e.g.ubuntu).EC2_SSH_KEY– private SSH key for that user.EC2_SSH_PORT– (optional) port, defaults to22if not set.EC2_ENV– multi-line secret containing the full contents of the.envfile used in production.
This is written to.envon the server during deployment.
Deployment Flow
- Push to
main. - GitHub Actions:
- Builds the app.
- Connects to EC2.
- Writes
.envfromEC2_ENV. - Runs
docker compose up -d --build. - Hits the health check URL (by default
http://localhost:3000/api/health).
- If the health check fails, the workflow:
- Resets the repo on EC2 to the previous commit.
- Re-runs
docker compose up -d --build.
This gives you a sharp deployment with an automatic rollback path.
OpenAI, Groq & AI Setup
OpenAI (embeddings + KB answers)
- Create an API key in the OpenAI dashboard.
- Add to
.env:
OPENAI_API_KEY="sk-..."
# Optional overrides:
# OPENAI_EMBEDDING_MODEL="text-embedding-3-small"
# OPENAI_EMBEDDING_DIMENSIONS="1024"
# OPENAI_CHAT_MODEL="gpt-4o-mini"
Embeddings are used when indexing knowledge documents, FAQs, and the structured store profile. KB Ask uses OpenAI chat first, then falls back to Groq.
Groq (storefront chat, Gmail helpers, KB fallback)
- Create an API key at Groq Console.
- Add to
.env:
GROQ_API_KEY="gsk_..."
# Optional: GROQ_MODEL="llama-3.1-8b-instant"
Database migration & re‑embedding
- Apply Prisma migrations:
npx prisma migrate deploy
- After changing embedding provider or dimensions, re‑embed:
npm run re-embed-knowledge-base
This regenerates vectors and tags chunk metadata with provider: openai (required for KB similarity search filters).
Prisma & Database
To inspect the database locally:
export DATABASE_URL='<YOUR_DB_URL>'
npx prisma studio
License
Private / All rights reserved unless explicitly stated otherwise.