LemurConnect is a social networking platform for professionals to connect, share, and collaborate. This Django-React application provides a robust backend API with a sleek, responsive frontend. https://lemurconnect.pacifictrout.com
- Introduction
- Features
- Technology Stack
- Docker
- Setup and Installation
- Configuration
- Troubleshooting Common Issues
- Contributing
- License
- Contact
This project uses Django as a backend framework to provide a RESTful API and React for the frontend to create an interactive user experience.
- User Authentication
- Profile Management
- Post/Update Sharing
- Real-time Notifications
- API Integration
- Frontend: React, Redux for state management
- Backend: Django REST Framework for a powerful API backend
- Database: SQLite for development, PostgreSQL for production
- Styling: Bootstrap for responsive design
This project is configured to run with Docker, simplifying development and deployment processes. Below are the instructions to get it up and running on your local machine.
Before you begin, ensure you have the following installed on your system:
-
Clone the Repository
If you haven't already done so, clone the repository to your local machine using:
git clone https://github.com/sapg-dev/Lemur-Connect-Social-Platform.git cd Lemur-Connect-Social-Platform
-
Build and Run the Containers
From the root directory of the project, where the docker-compose.yml file is located, run the following command to build and run the backend and frontend services in Docker containers:
docker-compose up --build
The --build flag is optional and is used to build the images before starting the containers. If you have already built the images and made no changes to the Dockerfiles, you can omit this flag and just run docker-compose up.
-
Accessing the Application
-
Once the containers are running, you can access the application as follows:
Frontend: Open your web browser and visit http://localhost:3000 Backend: The backend API will be available at http://localhost:8000 Caution: You may need to change axios.defaults.baseurl, and the proxy in packages.json
-
Stopping the Application
To stop the running containers, use the following command:
docker-compose down If you want to remove the volumes along with the containers, add the -v flag:
docker-compose down -v
- Clone the repository:
git clone https://github.com/sapg-dev/lemurconnect.git
- Navigate to the project directory:
cd lemurconnect
- Install backend dependencies:
pip install -r requirements.txt
- Apply migrations to create the database schema:
python manage.py migrate
- Collect static files(before that the build directory should be created and populated with the optimized build production):
python manage.py collectstatic --noinput
- Install frontend dependencies:
npm install
- Start the frontend development server:
npm start
- Start the backend development server:
python manage.py runserver
I had an enormous amount of trouble getting this project deployed online. At first, I thought that it would be much simpler to have the frontend hosted using Netlify, and hosting the backend through PythonAnywhere, and simply connecting both through a proxy set-up in packages.json, and changing the axios.defaults.baseURL to my PythonAnywhere domain. However, this solution did not work for a couple of reasons, to begin with, the Axios request was corrupted on arrival. The issues I encountered included CORS (Cross-Origin Resource Sharing) errors, which are common when the frontend and backend are hosted on different domains. Even after setting the proxy, the browser security model was blocking the requests from being executed. To resolve these issues, I had to ensure that the backend server provided the appropriate CORS headers to allow for cross-origin requests from the frontend domain. This involved configuring my PythonAnywhere backend to set headers like Access-Control-Allow-Origin to include my Netlify domain. I also made sure to return the correct headers for OPTIONS preflight requests, which are automatically made by browsers in a CORS context. After fixing the CORS configuration, I faced another hurdle: the proxy configuration in package.json was not being respected by Netlify upon deployment because it only works in a development environment created by create-react-app. For a production environment, I needed to set up a Netlify _redirects file or netlify.toml to handle proxying. Lastly, I discovered that the issue with Axios requests being "corrupted on arrival" was due to a misconfiguration in the way I was serializing data before sending it over Axios. I had to ensure that the request payloads were correctly formatted as JSON, and any necessary Content-Type headers were being set to application/json. Ultimately, despite my efforts to separate the frontend and backend between Netlify and PythonAnywhere, the solution didn’t work out as planned. The issues with Axios and CORS proved too complex to resolve within my project's timeline and with the hosting configurations I had initially chosen. After wrestling with numerous deployment errors and configuration mismatches, I decided to simplify the approach. I moved all components of my project to be served from PythonAnywhere. By hosting both the frontend and the backend on the same platform, I could avoid the CORS issues that arise with cross-domain requests entirely. I adapted my codebase to serve the React-built static files directly from PythonAnywhere, treating them as I would any static assets in a traditional web application. This change meant configuring my PythonAnywhere account to handle static files and point to the compiled React project as the root for my website's static resources. I updated my application's routes to render these static templates, which allowed me to maintain a single domain for both my API and the user interface without the need for complex proxy configurations. Rendering static templates through PythonAnywhere simplified the architecture, reduced points of failure, and allowed for a more straightforward debugging process. It was a compromise between my ideal deployment strategy and what was practical, ensuring that my project was online and functional for users. Sometimes, deploying both parts of a web application on the same service is the most effective way to manage and troubleshoot it, especially when external factors like time and complexity are at play.
By using pythonanywhere, I had to perform relatively small changes to my settings.py, and my index.js:
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CORS_ALLOW_ALL_ORIGINS = True
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'your-secret-key'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = [
'your-pythonanywhere-domain.com',
# ... other hostnames ...
]
CORS_ALLOWED_ORIGINS = [
'https://your-frontend-domain.com',
# ... additional origins ...
]
# Application definition
INSTALLED_APPS = [
# ... your Django apps ...
'corsheaders',
# ... other installed apps ...
]
MIDDLEWARE = [
# ... other middleware classes ...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# ... other middleware classes ...
]
ROOT_URLCONF = 'your_project.urls'
TEMPLATES = [
# ... your templates settings ...
]
TEMPLATES_DIR = os.path.join(BASE_DIR, '..', 'frontend', 'build')
WSGI_APPLICATION = 'your_project.wsgi.application'
# ... your database configuration ...
# ... your password validation configuration ...
# ... your user authentication model ...
# Internationalization
# ... your internationalization settings ...
STATICFILES_DIRS = [
os.path.join(BASE_DIR, '..', 'frontend', 'build', 'static'),
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticroot')
# ... your GitHub OAuth client configuration ...
And for the index.js file, I simply had to add this line:
// Set the base URL for all Axios requests
axios.defaults.baseURL = 'https://your-backend-domain.com';
This issue might have only been caused by my local machine. I had a node_modules folder placed outside of the root directory, which when I decided to use npm start/npm run build
would output a dependency error. A temporary solution I found was to:
- Run
npm ls babel-jest
to check for babel-jest installations. - Use
npm prune --production
to remove extraneous packages. - Update project dependencies with
npm update
.
but also change the start/build scripts in packages.json to : "start": "set \"NODE_OPTIONS=--openssl-legacy-provider\" && react-scripts start"
, of course change start to build for the build command. This solved the problem on the surface but not fully.
Ensure Django settings for STATIC_URL
and STATIC_ROOT
are configured properly and DEBUG
is True during development.
- Run
python manage.py migrate
to ensure all migrations are applied. - Check if the SQLite3 database file is present and intact.
Adjust build scripts for Netlify deployment to use the Linux environment settings.
I welcome contributions! Please read my CONTRIBUTING.md(soon to come) for details on my code of conduct and the process for submitting pull requests to this project.
This project is licensed under the MIT License - see the LICENSE.md file for details.
- Email: s@pacifictrout.com