From 60cd1d3d0d0e4a0b1dffef0776e341e50f6882c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20K?= <51174697+DanCodernaut@users.noreply.github.com> Date: Wed, 14 May 2025 16:58:17 +0200 Subject: [PATCH 1/4] update README.md --- README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e44ad9d..0a236bc 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,23 @@ # Subscribely
- + [![Subscribely Logo](https://i.imgur.com/hicXmxC.png)](https://subscribely-subscription-manager.vercel.app/)
- + [![Next.js](https://img.shields.io/badge/Next.js-15.2.3-black?style=flat-plastic&logo=next.js)](https://nextjs.org/) [![MongoDB](https://img.shields.io/badge/MongoDB-8.12-green?style=flat-plastic&logo=mongodb)](https://www.mongodb.com/) [![Vercel](https://img.shields.io/badge/Deployed_on-Vercel-black?style=flat-plastic&logo=vercel)](https://vercel.com) +[![Docker](https://img.shields.io/badge/Docker-Ready-blue?style=flat-plastic&logo=docker)](https://www.docker.com/) [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-plastic)](LICENSE)
## 📄 Overview + Subscribely is a creative project built to demonstrate a modern subscription management platform. This project has been in development for 2 months and serves as a showcase for implementing a comprehensive subscription system with role-based access controls. **Note:** This is not a real-world application solving an actual business problem, but rather a creative project demonstrating various technical implementations and solutions. @@ -27,18 +29,19 @@ Subscribely is a creative project built to demonstrate a modern subscription man ## ✨ Showcase | ![Image 1](https://github.com/user-attachments/assets/9e557f57-79a8-4ea7-9918-1b8cd3177d71) | ![Image 2](https://github.com/user-attachments/assets/f8aec892-249c-4561-9019-58116fd76c16) | -|--------------------------------|--------------------------------| +| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | ![Image 3](https://github.com/user-attachments/assets/6623ef73-e7e2-4f1f-a247-2500cf7ffbe8) | ![Image 4](https://github.com/user-attachments/assets/5bf05861-b21a-430d-bdd0-d2894664aa58) | - ## 🔧 Features ### Authentication + - User registration and login system - Role-based access control (Admin and User roles) - Secure authentication with JWT ### User Features + - Default balance in USD for new accounts - Subscription marketplace ("Subscription Store") - Active subscription management (up to 3 active subscriptions) @@ -46,12 +49,14 @@ Subscribely is a creative project built to demonstrate a modern subscription man - Profile settings with account deletion option ### Admin Features + - Create, edit, and delete subscription packages - View all user subscriptions across the platform - Ability to revoke user subscriptions with automatic email notification - Modify user account balances ### Subscription System + - Configurable subscription packages (name, description, price, status) - Customizable subscription durations (1 day, 14 days, 1 month, etc.) - Automatic balance deduction on purchase @@ -61,6 +66,7 @@ Subscribely is a creative project built to demonstrate a modern subscription man - Admin-initiated subscription revocation ## 📐 Tech Stack + - **Framework**: Next.js 15 with TypeScript - **Styling**: Tailwind CSS - **Database**: MongoDB with Mongoose @@ -71,8 +77,10 @@ Subscribely is a creative project built to demonstrate a modern subscription man - **Monitoring**: Sentry - **Security**: Arcjet - **Deployment**: Vercel +- **Containerization**: Docker and Docker Compose ## 🗂️ Project Structure + The project follows a standard Next.js App Router structure with server actions and API routes. ``` @@ -93,6 +101,8 @@ The project follows a standard Next.js App Router structure with server actions ├── .gitignore ├── .prettierrc.json ├── components.json +├── docker-compose.yml +├── Dockerfile ├── eslint.config.mjs ├── instrumentation-client.ts ├── instrumentation.ts @@ -109,6 +119,7 @@ The project follows a standard Next.js App Router structure with server actions ``` ## 🌐 Development Practices + - Strongly typed with TypeScript - Conventional commits for clear version history - Git workflow configured with Husky and lint-staged @@ -117,6 +128,8 @@ The project follows a standard Next.js App Router structure with server actions ## 📥 Installation +### Standard Installation + ```bash # Clone the repository git clone https://github.com/dan0dev/Subscribely.Subscription.Manager.git @@ -128,7 +141,34 @@ npm install npm run dev ``` +### Docker Installation + +The application can also be run using Docker and Docker Compose, which sets up both the application and MongoDB database in containers with automatic file watching for development. + +#### Prerequisites + +- [Docker](https://www.docker.com/get-started) (20.10.0 or higher) +- [Docker Compose](https://docs.docker.com/compose/install/) (v2.0.0 or higher) + +```bash +# Clone the repository +git clone https://github.com/dan0dev/Subscribely.Subscription.Manager.git + +# Navigate to the project directory +cd Subscribely.Subscription.Manager + +# Create .env file with your environment variables (see Environment Variables section) +# Then start the application with Docker Compose +docker compose up --build + +# For development with live file watching +docker compose up +``` + +The application will be available at `http://localhost:3000`. Any changes made to the source files will be automatically synchronized to the container through the volume mounts and hot-reloading will be triggered by Next.js. + ## 🌳 Environment Variables + Modify the `.env.local` file with your own variables data with the following: ``` @@ -145,9 +185,11 @@ SENTRY_AUTH_TOKEN= ``` ## 💻 Deployment + The application is deployed on Vercel. ## 📝 Todo + - Creating test role as account - Implement automatic subscription expiration (currently subscriptions don't expire automatically) - Add subscription renewal options @@ -160,7 +202,6 @@ Subscribely is an open-source project, and we welcome contributions of all kinds We use [GitHub Issues](https://github.com/dan0dev/Subscribely.Subscription.Manager/issues) for tracking bugs and feature requests. - ## 📃 License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. From 00b025da62ff87f4c33dc818bd44e76b487df7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20K?= <51174697+DanCodernaut@users.noreply.github.com> Date: Wed, 14 May 2025 16:58:30 +0200 Subject: [PATCH 2/4] update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index dd146b5..5adb050 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ next-env.d.ts # Sentry Config File .env.sentry-build-plugin + +mongodb_data/ From e83704ec7ba9aa0ec8824bdaf1360484f0b13d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20K?= <51174697+DanCodernaut@users.noreply.github.com> Date: Wed, 14 May 2025 17:23:14 +0200 Subject: [PATCH 3/4] feat(dev-env): setup Docker for local development environment --- .dockerignore | 34 ++++++++++++++++++++++++++++++++++ Dockerfile | 13 +++++++++++++ README.Docker.md | 22 ++++++++++++++++++++++ compose.yaml | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 README.Docker.md create mode 100644 compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..dc157ff --- /dev/null +++ b/.dockerignore @@ -0,0 +1,34 @@ +# Include any files or directories that you don't want to be copied to your +# container here (e.g., local build artifacts, temporary files, etc.). +# +# For more help, visit the .dockerignore file reference guide at +# https://docs.docker.com/go/build-context-dockerignore/ + +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.next +**/.cache +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/charts +**/docker-compose* +**/compose.y*ml +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +**/build +**/dist +LICENSE +README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d4d888e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM node + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +EXPOSE 3000 + +CMD npm run dev diff --git a/README.Docker.md b/README.Docker.md new file mode 100644 index 0000000..fa3048f --- /dev/null +++ b/README.Docker.md @@ -0,0 +1,22 @@ +### Building and running your application + +When you're ready, start your application by running: +`docker compose up --build`. + +Your application will be available at http://localhost:3000. + +### Deploying your application to the cloud + +First, build your image, e.g.: `docker build -t myapp .`. +If your cloud uses a different CPU architecture than your development +machine (e.g., you are on a Mac M1 and your cloud provider is amd64), +you'll want to build the image for that platform, e.g.: +`docker build --platform=linux/amd64 -t myapp .`. + +Then, push it to your registry, e.g. `docker push myregistry.com/myapp`. + +Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/) +docs for more detail on building and pushing. + +### References +* [Docker's Node.js guide](https://docs.docker.com/language/nodejs/) \ No newline at end of file diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..242cd10 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,32 @@ +version: "3.8" + +services: + frontend: + build: + context: . + dockerfile: Dockerfile + ports: + - 3000:3000 + develop: + watch: + - path: ./package.json + action: rebuild + - path: ./next.config.ts + action: rebuild + - path: ./package-lock.json + action: rebuild + - path: . + target: /app + action: sync + environment: + NODE_ENV: ${NODE_ENV:-development} + MONGODB_URI: ${MONGODB_URI} + JWT_SECRET: ${JWT_SECRET} + JWT_EXPIRES_IN: ${JWT_EXPIRES_IN} + GMAIL_USER: ${GMAIL_USER} + GMAIL_PASSWORD: ${GMAIL_PASSWORD} + ARCJET_KEY: ${ARCJET_KEY} + SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN} + volumes: + - ./.next:/app/.next + - ./node_modules:/app/node_modules From 9bce2298e399079a3abb71736a2cc0ece28b3e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20K?= <51174697+DanCodernaut@users.noreply.github.com> Date: Wed, 14 May 2025 17:55:10 +0200 Subject: [PATCH 4/4] feat(dev-env): setup Docker for local development environment --- Dockerfile | 14 ++++++++++++-- compose.yaml | 31 +++++++++++++++++++------------ next.config.ts | 23 ++++++++++++++++++++++- package.json | 4 ++-- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index d4d888e..a904fd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,23 @@ -FROM node +FROM node:18-alpine WORKDIR /app +# Copy package files first to leverage Docker cache COPY package*.json ./ +# Install dependencies RUN npm install +# Copy the rest of the app COPY . . +# Set environment variables +ENV PORT=3000 +ENV HOST=0.0.0.0 +ENV NODE_ENV=development + +# Expose the port EXPOSE 3000 -CMD npm run dev +# Start Next.js in development mode +CMD ["npm", "run", "dev"] diff --git a/compose.yaml b/compose.yaml index 242cd10..dfa319c 100644 --- a/compose.yaml +++ b/compose.yaml @@ -5,13 +5,14 @@ services: build: context: . dockerfile: Dockerfile + container_name: subscribely ports: - - 3000:3000 + - "3000:3000" develop: watch: - path: ./package.json action: rebuild - - path: ./next.config.ts + - path: ./next.config.js action: rebuild - path: ./package-lock.json action: rebuild @@ -19,14 +20,20 @@ services: target: /app action: sync environment: - NODE_ENV: ${NODE_ENV:-development} - MONGODB_URI: ${MONGODB_URI} - JWT_SECRET: ${JWT_SECRET} - JWT_EXPIRES_IN: ${JWT_EXPIRES_IN} - GMAIL_USER: ${GMAIL_USER} - GMAIL_PASSWORD: ${GMAIL_PASSWORD} - ARCJET_KEY: ${ARCJET_KEY} - SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN} + - NODE_ENV=development + - PORT=3000 + - HOST=0.0.0.0 + - MONGODB_URI=${MONGODB_URI} + - JWT_SECRET=${JWT_SECRET} + - JWT_EXPIRES_IN=${JWT_EXPIRES_IN} + - GMAIL_USER=${GMAIL_USER} + - GMAIL_PASSWORD=${GMAIL_PASSWORD} + - ARCJET_KEY=${ARCJET_KEY} + - SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN} volumes: - - ./.next:/app/.next - - ./node_modules:/app/node_modules + - .:/app + - /app/node_modules + - /app/.next + restart: unless-stopped + tty: true + stdin_open: true diff --git a/next.config.ts b/next.config.ts index 0e6dfc0..aaa6e73 100644 --- a/next.config.ts +++ b/next.config.ts @@ -41,7 +41,13 @@ const getCspHeader = () => { // API and WebSocket connections "connect-src": [ "'self'", - // Sentry error reporting (update with your actual Sentry DSN) + // Docker development additions + "http://localhost:*", + "http://127.0.0.1:*", + "http://0.0.0.0:*", + "ws://localhost:*", + "ws://0.0.0.0:*", + // Sentry error reporting "https://o4509210060587008.ingest.de.sentry.io", // Arcjet security service "https://api.arcjet.com", @@ -111,6 +117,21 @@ const nextConfig = { ]; }, + // Explicitly set server configuration + server: { + port: 3000, + hostname: "0.0.0.0", + }, + + // Required for webpack watcher in Docker + webpack: (config: import("webpack").Configuration): import("webpack").Configuration => { + config.watchOptions = { + poll: 1000, + aggregateTimeout: 300, + }; + return config; + }, + // HTTP headers for all responses async headers() { return [ diff --git a/package.json b/package.json index 4552b4f..107970e 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev --turbopack", + "dev": "next dev --hostname 0.0.0.0 --port 3000", "build": "next build", - "start": "next start", + "start": "next start --hostname 0.0.0.0 --port 3000", "lint": "next lint", "prepare": "husky" },