Modern, full-stack website for the SPATIAL (Spatial Analysis and Research) Center at UCSB. Built with React, Node.js, Express, GraphQL, and MongoDB.
- Dynamic Content Management - Admin interface for managing people, projects, and content
- Azure Blob Storage - Cloud-based image storage with local fallback
- GraphQL API - Efficient data fetching with Apollo Client/Server
- Authentication - Secure JWT-based admin authentication
- Responsive Design - Material-UI components for mobile-friendly interface
- Docker Support - Containerized deployment for easy scaling
- Comprehensive Testing - Jest tests for backend and frontend
- Node.js 20+
- MongoDB (local or Atlas)
- Docker (optional)
# Install dependencies
npm install
# Configure environment
cp server/env.example server/.env
cp client/env.example client/.env
# Edit .env files with your configuration
# Start development servers (runs both client and server)
npm run devVisit:
- Frontend: http://localhost:3000
- Backend: http://localhost:3001
- GraphQL: http://localhost:3001/graphql
- Development Guide - Local setup, testing, and development workflow
- Deployment Guide - Docker and Azure deployment instructions
- React 18
- Material-UI (MUI)
- Apollo Client (GraphQL)
- React Router
- Draft.js (Rich text editing)
- Node.js / Express
- Apollo Server (GraphQL)
- MongoDB / Mongoose
- JWT Authentication
- Multer + Azure Blob Storage
- Docker / Docker Compose
- Azure Container Registry
- Azure App Service / Container Instances
- Azure Blob Storage
spatial-website/
├── client/ # React frontend application
│ ├── src/
│ │ ├── components/ # Reusable React components
│ │ ├── pages/ # Page-level components
│ │ ├── utils/ # Client utilities (auth, API, config)
│ │ └── context/ # React context providers
│ └── package.json
├── server/ # Node.js backend API
│ ├── models/ # Mongoose data models
│ ├── routes/ # Express REST routes
│ ├── schemas/ # GraphQL schema and resolvers
│ ├── utils/ # Server utilities (auth, storage)
│ ├── seeders/ # Database seed data
│ └── server.js
├── Dockerfile # Production Docker image
├── docker-compose.yml # Docker orchestration
└── package.json # Root scripts
The website includes a full admin interface for content management:
- Secure login at
/login - JWT-based session management
- Auto-logout on token expiration
- People - Add/edit/delete team members with bios, photos, and links
- Projects - Manage research projects with descriptions and images
- Info Panels - Edit content sections on About, Events, and Opportunities pages
- Image Upload - Upload images to Azure Blob Storage or local storage
Default credentials (development only):
- Email:
admin@spatial.ucsb.edu - Password: Set in
.envfile
# Backend tests
cd server
npm test
# Frontend tests
cd client
npm test
# Run with coverage
npm run test:coverage# Build image
docker build -t spatial-website .
# Run with docker-compose
docker-compose up -d
# View logs
docker-compose logs -fSee DEPLOYMENT.md for detailed Azure setup including:
- Azure Container Registry
- Azure App Service / Container Instances
- Azure Blob Storage configuration
- MongoDB Atlas / Cosmos DB setup
| Variable | Description | Required |
|---|---|---|
NODE_ENV |
Environment (development/production) | Yes |
PORT |
Server port | Yes |
MONGODB_URI |
MongoDB connection string | Yes |
JWT_SECRET |
Secret for JWT signing | Yes |
USE_AZURE_STORAGE |
Use Azure Blob Storage (true/false) | No |
AZURE_STORAGE_CONNECTION_STRING |
Azure storage connection | If using Azure |
AZURE_CONTAINER_NAME |
Azure blob container name | If using Azure |
ADMIN_EMAIL |
Admin account email | Development only |
ADMIN_PASSWORD |
Admin account password | Development only |
| Variable | Description | Required |
|---|---|---|
REACT_APP_API_URL |
Backend API URL | Yes |
REACT_APP_GRAPHQL_URL |
GraphQL endpoint URL | Yes |
REACT_APP_UPLOAD_API_URL |
Upload API URL | Yes |
Images stored in server/public/images/
USE_AZURE_STORAGE=falseImages stored in Azure cloud
USE_AZURE_STORAGE=true
AZURE_STORAGE_CONNECTION_STRING=<your-connection-string>
AZURE_CONTAINER_NAME=spatial-imagesThe storage service automatically falls back to local storage if Azure credentials are invalid.
Access the GraphQL Playground at /graphql to explore the schema.
Queries:
people- Fetch all peopleprojects- Fetch all projectsinfoPanels- Fetch all info panels
Mutations: (Require Authentication)
addPerson,editPerson,deletePersonaddProject,editProject,deleteProjectaddInfoPanel,editInfoPanel,deleteInfoPanel
GET /api/health- Health check endpointPOST /api/images- Upload image (requires auth)DELETE /api/images/:id- Delete image (requires auth)GET /api/calendar/events- Get calendar events
- Create feature branch from
main - Make changes and add tests
- Run tests:
npm test - Commit with descriptive messages
- Create pull request
- JWT authentication for all admin operations
- Bcrypt password hashing
- CORS configuration
- Rate limiting on sensitive endpoints
- Environment variable protection
- Non-root Docker user
- Input validation and sanitization
- GraphQL for efficient data fetching
- React code splitting
- Image optimization
- Multi-stage Docker builds
- CDN-ready (Azure Blob Storage)
- Health checks for monitoring
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new features
- Ensure all tests pass
- Submit a pull request
Port already in use:
lsof -ti:3001 | xargs kill -9MongoDB connection failed:
- Check MongoDB is running
- Verify connection string in
.env - Check network/firewall settings
Images not uploading:
- Check Azure credentials if using Azure
- Verify admin authentication token
- Check file permissions for local storage
See DEVELOPMENT.md for more troubleshooting tips.
MIT License - see LICENSE file for details
For questions or issues:
- Email: admin@spatial.ucsb.edu
- GitHub Issues: Create an issue
- SPATIAL Research Center at UCSB
- Material-UI for component library
- Apollo for GraphQL implementation
- MongoDB for database
Built with ❤️ at UCSB