Just started
This commit is contained in:
commit
aea0071b3b
16 changed files with 356 additions and 0 deletions
26
Dockerfile
Normal file
26
Dockerfile
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Build stage for client
|
||||
FROM node:14 AS client-build
|
||||
WORKDIR /app/client
|
||||
COPY client/package*.json ./
|
||||
RUN npm install
|
||||
COPY client/ ./
|
||||
RUN npm run build -- --mode production
|
||||
|
||||
# Build stage for server
|
||||
FROM node:14 AS server-build
|
||||
WORKDIR /app/server
|
||||
COPY server/package*.json ./
|
||||
RUN npm install
|
||||
COPY server/ ./
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:14-alpine
|
||||
WORKDIR /app
|
||||
COPY --from=client-build /app/client/build ./client/build
|
||||
COPY --from=server-build /app/server/dist ./server/dist
|
||||
COPY --from=server-build /app/server/package*.json ./server/
|
||||
WORKDIR /app/server
|
||||
RUN npm install --only=production
|
||||
EXPOSE 5000
|
||||
CMD ["node", "dist/index.js"]
|
||||
28
README.md
Normal file
28
README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Missoula Council of the Deaf, Inc. Website
|
||||
|
||||
This repository contains the source code for the Missoula Council of the Deaf, Inc. (MCDi) website. The project is built using a MERN stack (MongoDB, Express, React, Node.js) with TypeScript and is containerized using Docker.
|
||||
|
||||
## Features
|
||||
|
||||
- Responsive design
|
||||
- Animated UI components using Framer Motion
|
||||
- Docker containerization for easy deployment
|
||||
- Express.js backend serving static React files
|
||||
|
||||
## Project Structure
|
||||
|
||||
The project is organized into client and server directories:
|
||||
|
||||
- `client/`: React frontend application
|
||||
- `server/`: Express.js backend application
|
||||
- `Dockerfile`: Multi-stage build for both client and server
|
||||
- `docker-compose.yml`: Docker Compose configuration for running the application
|
||||
|
||||
## Getting Started
|
||||
|
||||
To run this project locally:
|
||||
|
||||
1. Clone the repository
|
||||
2. Install Docker and Docker Compose
|
||||
3. Run `docker-compose up --build` in the project root directory
|
||||
4. Access the website at `http://localhost:5000`
|
||||
44
client/package.json
Normal file
44
client/package.json
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "mcdi-website-client",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"homepage": ".",
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.10.0",
|
||||
"styled-components": "^5.3.9",
|
||||
"framer-motion": "^10.12.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"typescript": "^5.0.4",
|
||||
"react-scripts": "5.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "GENERATE_SOURCEMAP=false react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
client/public/MCD-Inc._AOI_Bylaws.pdf
Normal file
BIN
client/public/MCD-Inc._AOI_Bylaws.pdf
Normal file
Binary file not shown.
20
client/public/index.html
Normal file
20
client/public/index.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Missoula Council of the Deaf, Inc. Website"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<title>Missoula Council of the Deaf, Inc.</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
23
client/src/App.tsx
Normal file
23
client/src/App.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import Header from './components/Header';
|
||||
import Footer from './components/Footer';
|
||||
import ComingSoon from './components/ComingSoon';
|
||||
|
||||
const AppContainer = styled.div`
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
padding-bottom: 60px; // Height of the footer
|
||||
`;
|
||||
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
<AppContainer>
|
||||
<Header />
|
||||
<ComingSoon />
|
||||
<Footer />
|
||||
</AppContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
31
client/src/components/ComingSoon.tsx
Normal file
31
client/src/components/ComingSoon.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const ComingSoonContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 60vh;
|
||||
`;
|
||||
|
||||
const ComingSoonText = styled(motion.h2)`
|
||||
font-size: 3rem;
|
||||
color: #8C1D40;
|
||||
`;
|
||||
|
||||
const ComingSoon: React.FC = () => {
|
||||
return (
|
||||
<ComingSoonContainer>
|
||||
<ComingSoonText
|
||||
initial={{ opacity: 0, y: -50 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 1 }}
|
||||
>
|
||||
COMING SOON
|
||||
</ComingSoonText>
|
||||
</ComingSoonContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ComingSoon;
|
||||
22
client/src/components/Footer.tsx
Normal file
22
client/src/components/Footer.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const FooterContainer = styled.footer`
|
||||
background-color: #8C1D40;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 1rem;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
return (
|
||||
<FooterContainer>
|
||||
<p>© MCDi 2024</p>
|
||||
</FooterContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
61
client/src/components/Header.tsx
Normal file
61
client/src/components/Header.tsx
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const HeaderContainer = styled.header`
|
||||
background-color: #8C1D40;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
`;
|
||||
|
||||
const Title = styled.h1`
|
||||
font-size: 1.5rem;
|
||||
text-align: right;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const Nav = styled.nav`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 1rem;
|
||||
`;
|
||||
|
||||
const NavItem = styled(motion.a)`
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
margin: 0 1rem;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
bottom: -5px;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
`;
|
||||
|
||||
const Header: React.FC = () => {
|
||||
return (
|
||||
<HeaderContainer>
|
||||
<Title>Missoula Council of the Deaf, Inc</Title>
|
||||
<Nav>
|
||||
<NavItem href="/" whileHover={{ scale: 1.1 }}>Home</NavItem>
|
||||
<NavItem href="/meet-board" whileHover={{ scale: 1.1 }}>Meet MCDi Board</NavItem>
|
||||
<NavItem href="/MCD-Inc._AOI_Bylaws.pdf" whileHover={{ scale: 1.1 }}>Bylaws</NavItem>
|
||||
<NavItem href="/news" whileHover={{ scale: 1.1 }}>News</NavItem>
|
||||
<NavItem href="/calendar" whileHover={{ scale: 1.1 }}>Calendar</NavItem>
|
||||
</Nav>
|
||||
</HeaderContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
11
client/src/index.tsx
Normal file
11
client/src/index.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import './styles/main.css';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
14
client/src/styles/main.css
Normal file
14
client/src/styles/main.css
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
20
client/tsconfig.json
Normal file
20
client/tsconfig.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
8
docker-compose.yml
Normal file
8
docker-compose.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
version: '3'
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
ports:
|
||||
- "5000:5000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
20
server/package.json
Normal file
20
server/package.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "mcdi-website-server",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"start": "node dist/index.js",
|
||||
"build": "tsc",
|
||||
"dev": "ts-node-dev --respawn --transpile-only src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.17.1",
|
||||
"mongoose": "^6.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "^16.11.6",
|
||||
"ts-node-dev": "^1.1.8",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
||||
17
server/src/index.ts
Normal file
17
server/src/index.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import express from 'express';
|
||||
import path from 'path';
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
app.use(express.static(path.join(__dirname, '../../client/build')));
|
||||
console.log('Serving static files from:', path.join(__dirname, '../../client/build'));
|
||||
|
||||
app.get('*', (req, res) => {
|
||||
console.log('Serving index.html for path:', req.path);
|
||||
res.sendFile(path.join(__dirname, '../../client/build/index.html'));
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running on port ${PORT}`);
|
||||
});
|
||||
11
server/tsconfig.json
Normal file
11
server/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue