diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d48e59afa --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules/ +.next/ +dist/ +build/ +.terraform/ +*.tfstate +*.tfstate.backup +.env +.env.local +__pycache__/ +venv/ diff --git a/Terraform/environments/dev/.terraform.lock.hcl b/Terraform/environments/dev/.terraform.lock.hcl new file mode 100644 index 000000000..92a2bcccd --- /dev/null +++ b/Terraform/environments/dev/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.100.0" + constraints = "~> 5.0" + hashes = [ + "h1:H3mU/7URhP0uCRGK8jeQRKxx2XFzEqLiOq/L2Bbiaxs=", + "zh:054b8dd49f0549c9a7cc27d159e45327b7b65cf404da5e5a20da154b90b8a644", + "zh:0b97bf8d5e03d15d83cc40b0530a1f84b459354939ba6f135a0086c20ebbe6b2", + "zh:1589a2266af699cbd5d80737a0fe02e54ec9cf2ca54e7e00ac51c7359056f274", + "zh:6330766f1d85f01ae6ea90d1b214b8b74cc8c1badc4696b165b36ddd4cc15f7b", + "zh:7c8c2e30d8e55291b86fcb64bdf6c25489d538688545eb48fd74ad622e5d3862", + "zh:99b1003bd9bd32ee323544da897148f46a527f622dc3971af63ea3e251596342", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9f8b909d3ec50ade83c8062290378b1ec553edef6a447c56dadc01a99f4eaa93", + "zh:aaef921ff9aabaf8b1869a86d692ebd24fbd4e12c21205034bb679b9caf883a2", + "zh:ac882313207aba00dd5a76dbd572a0ddc818bb9cbf5c9d61b28fe30efaec951e", + "zh:bb64e8aff37becab373a1a0cc1080990785304141af42ed6aa3dd4913b000421", + "zh:dfe495f6621df5540d9c92ad40b8067376350b005c637ea6efac5dc15028add4", + "zh:f0ddf0eaf052766cfe09dea8200a946519f653c384ab4336e2a4a64fdd6310e9", + "zh:f1b7e684f4c7ae1eed272b6de7d2049bb87a0275cb04dbb7cda6636f600699c9", + "zh:ff461571e3f233699bf690db319dfe46aec75e58726636a0d97dd9ac6e32fb70", + ] +} diff --git a/Terraform/environments/dev/backend.tf b/Terraform/environments/dev/backend.tf new file mode 100644 index 000000000..c5732a83a --- /dev/null +++ b/Terraform/environments/dev/backend.tf @@ -0,0 +1,9 @@ +terraform { + backend "s3" { + bucket = "shamitha-0924" + key = "dev/terraform.tfstate" + region = "ap-south-1" + dynamodb_table = "terraform-lock-table" + encrypt = true + } +} \ No newline at end of file diff --git a/Terraform/environments/dev/main.tf b/Terraform/environments/dev/main.tf new file mode 100644 index 000000000..5cf72ae7e --- /dev/null +++ b/Terraform/environments/dev/main.tf @@ -0,0 +1,25 @@ +module "vpc" { + source = "../../modules/vpc" + + vpc_cidr = var.vpc_cidr +} + +module "security_group" { + source = "../../modules/security-groups" + + vpc_id = module.vpc.vpc_id +} + +module "iam" { + source = "../../modules/iam" +} + +module "ec2" { + source = "../../modules/ec2" + + ami_id = var.ami_id + instance_type = var.instance_type + subnet_id = module.vpc.public_subnet_id + sg_id = module.security_group.sg_id + instance_profile = module.iam.instance_profile +} \ No newline at end of file diff --git a/Terraform/environments/dev/providers.tf b/Terraform/environments/dev/providers.tf new file mode 100644 index 000000000..a475680e8 --- /dev/null +++ b/Terraform/environments/dev/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = var.region +} diff --git a/Terraform/environments/dev/terraform.tfvars b/Terraform/environments/dev/terraform.tfvars new file mode 100644 index 000000000..aa77bd0cd --- /dev/null +++ b/Terraform/environments/dev/terraform.tfvars @@ -0,0 +1,4 @@ +region = "ap-south-1" +vpc_cidr = "10.0.0.0/16" +ami_id = "ami-0607784b46cbe5816" +instance_type = "t2.medium" \ No newline at end of file diff --git a/Terraform/environments/dev/variables.tf b/Terraform/environments/dev/variables.tf new file mode 100644 index 000000000..aa3addcba --- /dev/null +++ b/Terraform/environments/dev/variables.tf @@ -0,0 +1,4 @@ +variable "vpc_cidr" {} +variable "ami_id" {} +variable "instance_type" {} +variable "region" {} \ No newline at end of file diff --git a/Terraform/modules/ec2/main.tf b/Terraform/modules/ec2/main.tf new file mode 100644 index 000000000..147ede0f8 --- /dev/null +++ b/Terraform/modules/ec2/main.tf @@ -0,0 +1,11 @@ +resource "aws_instance" "main" { + ami = var.ami_id + instance_type = var.instance_type + subnet_id = var.subnet_id + vpc_security_group_ids = [var.sg_id] + iam_instance_profile = var.instance_profile + + tags = { + Name = "Terraform-EC2" + } +} \ No newline at end of file diff --git a/Terraform/modules/ec2/outputs.tf b/Terraform/modules/ec2/outputs.tf new file mode 100644 index 000000000..a08e0a56a --- /dev/null +++ b/Terraform/modules/ec2/outputs.tf @@ -0,0 +1,14 @@ +output "instance_id" { + description = "EC2 Instance ID" + value = aws_instance.main.id +} + +output "public_ip" { + description = "Public IP of EC2" + value = aws_instance.main.public_ip +} + +output "private_ip" { + description = "Private IP of EC2" + value = aws_instance.main.private_ip +} \ No newline at end of file diff --git a/Terraform/modules/ec2/variables.tf b/Terraform/modules/ec2/variables.tf new file mode 100644 index 000000000..5b895507d --- /dev/null +++ b/Terraform/modules/ec2/variables.tf @@ -0,0 +1,5 @@ +variable "ami_id" {} +variable "instance_type" {} +variable "subnet_id" {} +variable "sg_id" {} +variable "instance_profile" {} \ No newline at end of file diff --git a/Terraform/modules/iam/main.tf b/Terraform/modules/iam/main.tf new file mode 100644 index 000000000..d72ffe341 --- /dev/null +++ b/Terraform/modules/iam/main.tf @@ -0,0 +1,19 @@ +resource "aws_iam_role" "ec2_role" { + name = "ec2-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + }] + }) +} + +resource "aws_iam_instance_profile" "profile" { + name = "ec2-instance-profile" + role = aws_iam_role.ec2_role.name +} \ No newline at end of file diff --git a/Terraform/modules/iam/outputs.tf b/Terraform/modules/iam/outputs.tf new file mode 100644 index 000000000..9319ad844 --- /dev/null +++ b/Terraform/modules/iam/outputs.tf @@ -0,0 +1,3 @@ +output "instance_profile" { + value = aws_iam_instance_profile.profile.name +} \ No newline at end of file diff --git a/Terraform/modules/security-groups/main.tf b/Terraform/modules/security-groups/main.tf new file mode 100644 index 000000000..e996ab155 --- /dev/null +++ b/Terraform/modules/security-groups/main.tf @@ -0,0 +1,45 @@ +resource "aws_security_group" "main" { + vpc_id = var.vpc_id + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + +ingress { + from_port = 8000 + to_port = 8000 + protocol = "tcp" + cidr_blocks = ["49.204.123.10/32"] + } + + ingress { + from_port = 3000 + to_port = 3000 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + +ingress { + from_port = 8080 + to_port = 8080 + protocol = "tcp" + cidr_blocks = ["49.204.123.10/32"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} \ No newline at end of file diff --git a/Terraform/modules/security-groups/outputs.tf b/Terraform/modules/security-groups/outputs.tf new file mode 100644 index 000000000..1d89af691 --- /dev/null +++ b/Terraform/modules/security-groups/outputs.tf @@ -0,0 +1,3 @@ +output "sg_id" { + value = aws_security_group.main.id +} \ No newline at end of file diff --git a/Terraform/modules/security-groups/variables.tf b/Terraform/modules/security-groups/variables.tf new file mode 100644 index 000000000..b7bf843b5 --- /dev/null +++ b/Terraform/modules/security-groups/variables.tf @@ -0,0 +1 @@ +variable "vpc_id" {} \ No newline at end of file diff --git a/Terraform/modules/vpc/main.tf b/Terraform/modules/vpc/main.tf new file mode 100644 index 000000000..92d6e7d86 --- /dev/null +++ b/Terraform/modules/vpc/main.tf @@ -0,0 +1,28 @@ +resource "aws_vpc" "main" { + cidr_block = var.vpc_cidr +} + +resource "aws_subnet" "public" { + vpc_id = aws_vpc.main.id + cidr_block = "10.0.1.0/24" + map_public_ip_on_launch = true +} + +resource "aws_internet_gateway" "igw" { + vpc_id = aws_vpc.main.id +} + +resource "aws_route_table" "public_rt" { + vpc_id = aws_vpc.main.id +} + +resource "aws_route" "internet_access" { + route_table_id = aws_route_table.public_rt.id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw.id +} + +resource "aws_route_table_association" "public_assoc" { + subnet_id = aws_subnet.public.id + route_table_id = aws_route_table.public_rt.id +} \ No newline at end of file diff --git a/Terraform/modules/vpc/outputs.tf b/Terraform/modules/vpc/outputs.tf new file mode 100644 index 000000000..9d9ebdb61 --- /dev/null +++ b/Terraform/modules/vpc/outputs.tf @@ -0,0 +1,7 @@ +output "vpc_id" { + value = aws_vpc.main.id +} + +output "public_subnet_id" { + value = aws_subnet.public.id +} \ No newline at end of file diff --git a/Terraform/modules/vpc/variables.tf b/Terraform/modules/vpc/variables.tf new file mode 100644 index 000000000..fb1a1ec6f --- /dev/null +++ b/Terraform/modules/vpc/variables.tf @@ -0,0 +1 @@ +variable "vpc_cidr" {} \ No newline at end of file diff --git a/Terraform/providers.tf b/Terraform/providers.tf new file mode 100644 index 000000000..af34e7939 --- /dev/null +++ b/Terraform/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = var.region +} \ No newline at end of file diff --git a/Terraform/terraform.tfvars b/Terraform/terraform.tfvars new file mode 100644 index 000000000..b332c55e4 --- /dev/null +++ b/Terraform/terraform.tfvars @@ -0,0 +1 @@ +region = "ap-south-1" \ No newline at end of file diff --git a/Terraform/variables.tf b/Terraform/variables.tf new file mode 100644 index 000000000..421266a07 --- /dev/null +++ b/Terraform/variables.tf @@ -0,0 +1,4 @@ +variable "region" { + description = "AWS region" + type = string +} \ No newline at end of file diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 000000000..c7a512535 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,10 @@ +__pycache__ +*.pyc +*.pyo +venv +.env +.git +.gitignore +README.md +.pytest_cache +.coverage diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 000000000..b14344c18 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,14 @@ +# Python Backend +FROM python:3.11-slim + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 5000 + +CMD ["python", "app/main.py"] diff --git a/backend/app/main.py b/backend/app/main.py index be0227831..8f7912306 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -24,3 +24,7 @@ async def health_check(): @app.get("/api/message") async def get_message(): return {"message": "You've successfully integrated the backend!"} + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=5000) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..fe51e3ae3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.8' + +services: + backend: + build: ./backend + container_name: devops-backend + ports: + - "5000:5000" + environment: + - FLASK_APP=app/main.py + - FLASK_ENV=development + volumes: + - ./backend:/app + command: python app/main.py + + frontend: + build: ./frontend + container_name: devops-frontend + ports: + - "3000:3000" + environment: + - NEXT_PUBLIC_API_URL=http://localhost:5000 + volumes: + - ./frontend:/app + - /app/node_modules + command: npm run dev + depends_on: + - backend + +networks: + default: + name: devops-network diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 000000000..c00459444 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,10 @@ +node_modules +npm-debug.log +.git +.gitignore +README.md +.env +.env.local +build +dist +coverage diff --git a/frontend/.env.local b/frontend/.env.local index 600de8dfe..0c368c30a 100644 --- a/frontend/.env.local +++ b/frontend/.env.local @@ -1 +1 @@ -NEXT_PUBLIC_API_URL=http://localhost:8000 +NEXT_PUBLIC_API_URL=http://localhost:5000 diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 000000000..d54d07da3 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,14 @@ +# Node.js Frontend +FROM node:18-alpine + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +EXPOSE 3000 + +CMD ["npm", "run", "dev"] diff --git a/frontend/pages/index.js b/frontend/pages/index.js index 367ef97f9..b145214cb 100644 --- a/frontend/pages/index.js +++ b/frontend/pages/index.js @@ -4,24 +4,36 @@ import axios from 'axios'; export default function Home() { const [message, setMessage] = useState('Loading...'); - const [status, setStatus] = useState(''); + const [status, setStatus] = useState('Connecting...'); useEffect(() => { const fetchData = async () => { try { + const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000'; + console.log('Backend URL:', apiUrl); + // First check if backend is healthy - const healthCheck = await axios.get(`${process.env.NEXT_PUBLIC_API_URL}/api/health`); + const healthCheck = await axios.get(`${apiUrl}/api/health`, { + timeout: 5000 + }); + + console.log('Health check response:', healthCheck.data); if (healthCheck.data.status === 'healthy') { - setStatus('Backend is connected!'); + setStatus('✓ Backend is connected!'); // Then fetch the message - const response = await axios.get(`${process.env.NEXT_PUBLIC_API_URL}/api/message`); + const response = await axios.get(`${apiUrl}/api/message`, { + timeout: 5000 + }); setMessage(response.data.message); + console.log('Message response:', response.data); } } catch (error) { + console.error('Full error:', error); + console.error('Error message:', error.message); + console.error('Error response:', error.response?.data); setMessage('Failed to connect to the backend'); - setStatus('Backend connection failed'); - console.error('Error:', error); + setStatus('✗ Backend connection failed'); } }; @@ -39,14 +51,14 @@ export default function Home() {

DevOps Assignment

-

Status: {status}

+

Status: {status}

Backend Message:

{message}

-

Backend URL: {process.env.NEXT_PUBLIC_API_URL}

+

Backend URL: {process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000'}

diff --git a/node-python-workspace/.vscode/launch.json b/node-python-workspace/.vscode/launch.json new file mode 100644 index 000000000..c618201f0 --- /dev/null +++ b/node-python-workspace/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Frontend", + "skipFiles": ["/**"], + "program": "${workspaceFolder}/frontend/src/index.js", + "outFiles": ["${workspaceFolder}/frontend/**/*.js"], + "env": { + "NODE_ENV": "development" + } + }, + { + "name": "Python: Flask", + "type": "python", + "request": "launch", + "module": "flask", + "env": { + "FLASK_APP": "backend/app.py", + "FLASK_ENV": "development" + }, + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/node-python-workspace/.vscode/settings.json b/node-python-workspace/.vscode/settings.json new file mode 100644 index 000000000..e316ff7dc --- /dev/null +++ b/node-python-workspace/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "python.pythonPath": "backend/venv/bin/python", + "editor.formatOnSave": true, + "files.exclude": { + "**/__pycache__": true, + "**/*.pyc": true + }, + "eslint.enable": true, + "eslint.validate": [ + "javascript", + "javascriptreact" + ], + "prettier.requireConfig": true +} \ No newline at end of file diff --git a/node-python-workspace/README.md b/node-python-workspace/README.md new file mode 100644 index 000000000..c23b9ee20 --- /dev/null +++ b/node-python-workspace/README.md @@ -0,0 +1,93 @@ +# Node-Python Workspace + +This project is a full-stack application that combines a Node.js frontend with a Python backend. Below are the details for setting up and running the project. + +## Project Structure + +``` +node-python-workspace +├── frontend # Node.js frontend application +│ ├── package.json # Frontend dependencies and scripts +│ ├── .env.example # Example environment variables for frontend +│ ├── src # Source files for the frontend +│ │ ├── index.js # Entry point for the frontend application +│ │ └── components # React components +│ │ └── App.js # Main component for the frontend +│ └── public # Public assets for the frontend +│ └── index.html # Main HTML file for the frontend +├── backend # Python backend application +│ ├── requirements.txt # Python dependencies for the backend +│ ├── app.py # Entry point for the backend application +│ ├── src # Source files for the backend +│ │ └── api.py # API endpoint definitions +│ └── tests # Unit tests for the backend +│ └── test_api.py # Tests for the API endpoints +├── .vscode # VS Code configuration files +│ ├── launch.json # Debugging configuration +│ └── settings.json # Workspace settings +├── node-python.code-workspace # Workspace configuration +├── .gitignore # Files and directories to ignore by Git +└── README.md # Project documentation +``` + +## Getting Started + +### Prerequisites + +- Node.js and npm (for the frontend) +- Python 3 and pip (for the backend) + +### Frontend Setup + +1. Navigate to the `frontend` directory: + ``` + cd frontend + ``` + +2. Install the dependencies: + ``` + npm install + ``` + +3. Create a `.env` file based on the `.env.example` file and configure your environment variables. + +4. Start the frontend application: + ``` + npm start + ``` + +### Backend Setup + +1. Navigate to the `backend` directory: + ``` + cd backend + ``` + +2. Install the dependencies: + ``` + pip install -r requirements.txt + ``` + +3. Start the backend application: + ``` + python app.py + ``` + +## Usage + +Once both the frontend and backend are running, you can access the frontend application in your web browser at `http://localhost:3000` (or the port specified in your frontend configuration). The backend API will be available at `http://localhost:5000` (or the port specified in your backend configuration). + +## Running Tests + +To run the backend tests, navigate to the `backend` directory and execute: +``` +pytest tests/test_api.py +``` + +## Contributing + +Feel free to submit issues or pull requests for any improvements or bug fixes. + +## License + +This project is licensed under the MIT License. \ No newline at end of file diff --git a/node-python-workspace/backend/app.py b/node-python-workspace/backend/app.py new file mode 100644 index 000000000..8a9c2d682 --- /dev/null +++ b/node-python-workspace/backend/app.py @@ -0,0 +1,10 @@ +from flask import Flask + +app = Flask(__name__) + +@app.route('/') +def home(): + return "Welcome to the Node-Python Workspace!" + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/node-python-workspace/backend/requirements.txt b/node-python-workspace/backend/requirements.txt new file mode 100644 index 000000000..dbc6687c1 --- /dev/null +++ b/node-python-workspace/backend/requirements.txt @@ -0,0 +1,3 @@ +Flask +requests +pytest \ No newline at end of file diff --git a/node-python-workspace/backend/src/api.py b/node-python-workspace/backend/src/api.py new file mode 100644 index 000000000..6fee5ec0c --- /dev/null +++ b/node-python-workspace/backend/src/api.py @@ -0,0 +1,15 @@ +from flask import Flask, jsonify, request + +app = Flask(__name__) + +@app.route('/api/example', methods=['GET']) +def example_endpoint(): + return jsonify({"message": "This is an example endpoint."}) + +@app.route('/api/data', methods=['POST']) +def data_endpoint(): + data = request.json + return jsonify({"received": data}), 201 + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/node-python-workspace/backend/tests/test_api.py b/node-python-workspace/backend/tests/test_api.py new file mode 100644 index 000000000..ac1f8d897 --- /dev/null +++ b/node-python-workspace/backend/tests/test_api.py @@ -0,0 +1,15 @@ +import unittest +from src.api import app + +class APITestCase(unittest.TestCase): + def setUp(self): + self.app = app.test_client() + self.app.testing = True + + def test_example_endpoint(self): + response = self.app.get('/api/example') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {'message': 'Hello, World!'}) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/node-python-workspace/frontend/.env.example b/node-python-workspace/frontend/.env.example new file mode 100644 index 000000000..61f16d160 --- /dev/null +++ b/node-python-workspace/frontend/.env.example @@ -0,0 +1,5 @@ +DATABASE_URL=your_database_url +API_KEY=your_api_key +NODE_ENV=development +PORT=3000 +REACT_APP_API_URL=http://localhost:5000/api \ No newline at end of file diff --git a/node-python-workspace/frontend/package.json b/node-python-workspace/frontend/package.json new file mode 100644 index 000000000..0a389ed61 --- /dev/null +++ b/node-python-workspace/frontend/package.json @@ -0,0 +1,23 @@ +{ + "name": "node-python-workspace", + "version": "1.0.0", + "description": "A project combining a Node.js frontend and a Python backend.", + "main": "src/index.js", + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "dependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-scripts": "4.0.3" + }, + "devDependencies": { + "eslint": "^7.32.0", + "eslint-plugin-react": "^7.27.1" + }, + "homepage": ".", + "license": "MIT" +} \ No newline at end of file diff --git a/node-python-workspace/frontend/public/index.html b/node-python-workspace/frontend/public/index.html new file mode 100644 index 000000000..2def81e76 --- /dev/null +++ b/node-python-workspace/frontend/public/index.html @@ -0,0 +1,11 @@ + + + + + + Node-Python Workspace + + +
+ + \ No newline at end of file diff --git a/node-python-workspace/frontend/src/components/App.js b/node-python-workspace/frontend/src/components/App.js new file mode 100644 index 000000000..f1c37ffd1 --- /dev/null +++ b/node-python-workspace/frontend/src/components/App.js @@ -0,0 +1,12 @@ +import React from 'react'; + +function App() { + return ( +
+

Welcome to the Node.js and Python Workspace

+

This is the main application component.

+
+ ); +} + +export default App; \ No newline at end of file diff --git a/node-python-workspace/frontend/src/index.js b/node-python-workspace/frontend/src/index.js new file mode 100644 index 000000000..c9a80bd9f --- /dev/null +++ b/node-python-workspace/frontend/src/index.js @@ -0,0 +1,13 @@ +// This file is the entry point for the frontend application. +// It initializes the application and renders the main component. + +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './components/App'; + +ReactDOM.render( + + + , + document.getElementById('root') +); \ No newline at end of file diff --git a/node-python-workspace/node-python.code-workspace b/node-python-workspace/node-python.code-workspace new file mode 100644 index 000000000..10f7d7054 --- /dev/null +++ b/node-python-workspace/node-python.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "frontend" + }, + { + "path": "backend" + } + ], + "settings": {} +} \ No newline at end of file