Spaces:
Running
Running
Mark Duppenthaler
commited on
Commit
·
f762ee5
1
Parent(s):
7351a22
Initial boilerplate for flask server running react frontend on typescript, tailwind, daisyui
Browse files- .dockerignore +16 -0
- .gitignore +58 -0
- Dockerfile +32 -0
- README.md +26 -0
- backend/app.py +17 -0
- backend/requirements.txt +3 -0
- frontend/index.html +13 -0
- frontend/package.json +28 -0
- frontend/src/App.tsx +26 -0
- frontend/src/index.css +3 -0
- frontend/src/main.tsx +10 -0
- frontend/src/vite-env.d.ts +1 -0
- frontend/tailwind.config.js +14 -0
- frontend/tsconfig.json +21 -0
- frontend/vite.config.ts +11 -0
- package-lock.json +40 -0
- package.json +6 -0
.dockerignore
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
node_modules
|
2 |
+
npm-debug.log
|
3 |
+
frontend/node_modules
|
4 |
+
frontend/dist
|
5 |
+
.git
|
6 |
+
.gitignore
|
7 |
+
.vscode
|
8 |
+
__pycache__
|
9 |
+
*.pyc
|
10 |
+
*.pyo
|
11 |
+
*.pyd
|
12 |
+
.Python
|
13 |
+
.env
|
14 |
+
env/
|
15 |
+
venv/
|
16 |
+
ENV/
|
.gitignore
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Byte-compiled / optimized / DLL files
|
2 |
+
__pycache__/
|
3 |
+
*.py[cod]
|
4 |
+
*$py.class
|
5 |
+
|
6 |
+
# C extensions
|
7 |
+
*.so
|
8 |
+
|
9 |
+
# Distribution / packaging
|
10 |
+
dist/
|
11 |
+
build/
|
12 |
+
*.egg-info/
|
13 |
+
|
14 |
+
# Virtual environments
|
15 |
+
venv/
|
16 |
+
env/
|
17 |
+
.env/
|
18 |
+
.venv/
|
19 |
+
ENV/
|
20 |
+
|
21 |
+
# IDE specific files
|
22 |
+
.idea/
|
23 |
+
.vscode/
|
24 |
+
*.swp
|
25 |
+
*.swo
|
26 |
+
.DS_Store
|
27 |
+
|
28 |
+
# Logs
|
29 |
+
logs/
|
30 |
+
*.log
|
31 |
+
|
32 |
+
# Local configuration
|
33 |
+
.env
|
34 |
+
.env.local
|
35 |
+
.env.development.local
|
36 |
+
.env.test.local
|
37 |
+
.env.production.local
|
38 |
+
|
39 |
+
# Dependencies
|
40 |
+
node_modules/
|
41 |
+
|
42 |
+
# Coverage reports
|
43 |
+
htmlcov/
|
44 |
+
.coverage
|
45 |
+
.coverage.*
|
46 |
+
coverage.xml
|
47 |
+
*.cover
|
48 |
+
|
49 |
+
# Database
|
50 |
+
*.db
|
51 |
+
*.sqlite3
|
52 |
+
|
53 |
+
# Jupyter Notebook
|
54 |
+
.ipynb_checkpoints
|
55 |
+
|
56 |
+
# Temporary files
|
57 |
+
tmp/
|
58 |
+
temp/
|
Dockerfile
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM node:18-alpine AS frontend-build
|
2 |
+
|
3 |
+
WORKDIR /app/frontend
|
4 |
+
COPY frontend/package.json frontend/package-lock.json* ./
|
5 |
+
RUN npm install
|
6 |
+
COPY frontend/ ./
|
7 |
+
RUN npm run build
|
8 |
+
|
9 |
+
FROM python:3.9-slim
|
10 |
+
|
11 |
+
WORKDIR /app/backend
|
12 |
+
|
13 |
+
# Copy frontend build
|
14 |
+
COPY --from=frontend-build /app/frontend/dist /app/frontend/dist
|
15 |
+
|
16 |
+
# Copy and install backend requirements
|
17 |
+
COPY backend/ .
|
18 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
19 |
+
|
20 |
+
# Set environment variables
|
21 |
+
ENV PYTHONUNBUFFERED=1
|
22 |
+
ENV PYTHONDONTWRITEBYTECODE=1
|
23 |
+
ENV FLASK_APP=backend/app.py
|
24 |
+
ENV FLASK_ENV=development
|
25 |
+
|
26 |
+
# Expose the port the app will run on
|
27 |
+
EXPOSE 7860
|
28 |
+
|
29 |
+
WORKDIR /app
|
30 |
+
|
31 |
+
# Command to run the application
|
32 |
+
CMD ["flask", "run", "--host=0.0.0.0", "--port=7860"]
|
README.md
CHANGED
@@ -9,3 +9,29 @@ short_description: POC development
|
|
9 |
---
|
10 |
|
11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
---
|
10 |
|
11 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
12 |
+
|
13 |
+
|
14 |
+
## Docker Build Instructions
|
15 |
+
|
16 |
+
### Prerequisites
|
17 |
+
- Docker installed on your system
|
18 |
+
- Git repository cloned locally
|
19 |
+
|
20 |
+
### Build Steps
|
21 |
+
|
22 |
+
1. Navigate to the project directory:
|
23 |
+
```bash
|
24 |
+
cd /path/to/omniseal_dev
|
25 |
+
```
|
26 |
+
|
27 |
+
2. Build the Docker image:
|
28 |
+
```bash
|
29 |
+
docker build -t omniseal-dev .
|
30 |
+
```
|
31 |
+
|
32 |
+
3. Run the container (this runs in auto-reload mode when you update python files in the backend directory):
|
33 |
+
```bash
|
34 |
+
docker run -p 7860:7860 -v $(pwd)/backend:/app/backend flask-react-app
|
35 |
+
```
|
36 |
+
|
37 |
+
4. Access the application at `http://localhost:7860`
|
backend/app.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, send_from_directory
|
2 |
+
import os
|
3 |
+
import logging
|
4 |
+
|
5 |
+
logger = logging.getLogger(__name__)
|
6 |
+
app = Flask(__name__, static_folder="../frontend/dist", static_url_path="")
|
7 |
+
|
8 |
+
logger.setLevel(logging.INFO)
|
9 |
+
|
10 |
+
|
11 |
+
@app.route("/")
|
12 |
+
def index():
|
13 |
+
return send_from_directory(app.static_folder, "index.html")
|
14 |
+
|
15 |
+
|
16 |
+
if __name__ == "__main__":
|
17 |
+
app.run(host="0.0.0.0", port=7860, debug=True, use_reloader=True)
|
backend/requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
Flask==2.0.1
|
2 |
+
Werkzeug==2.0.1
|
3 |
+
watchdog
|
frontend/index.html
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8" />
|
5 |
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
+
<title>Flask + React App</title>
|
8 |
+
</head>
|
9 |
+
<body>
|
10 |
+
<div id="root"></div>
|
11 |
+
<script type="module" src="/src/main.tsx"></script>
|
12 |
+
</body>
|
13 |
+
</html>
|
frontend/package.json
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "frontend",
|
3 |
+
"private": true,
|
4 |
+
"version": "0.0.0",
|
5 |
+
"type": "module",
|
6 |
+
"scripts": {
|
7 |
+
"dev": "vite",
|
8 |
+
"build": "tsc && vite build",
|
9 |
+
"preview": "vite preview"
|
10 |
+
},
|
11 |
+
"dependencies": {
|
12 |
+
"react": "^18.2.0",
|
13 |
+
"react-dom": "^18.2.0"
|
14 |
+
},
|
15 |
+
"devDependencies": {
|
16 |
+
"@types/react": "^18.2.15",
|
17 |
+
"@types/react-dom": "^18.2.7",
|
18 |
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
19 |
+
"@typescript-eslint/parser": "^6.0.0",
|
20 |
+
"@vitejs/plugin-react": "^4.0.3",
|
21 |
+
"autoprefixer": "^10.4.14",
|
22 |
+
"daisyui": "^3.5.0",
|
23 |
+
"postcss": "^8.4.27",
|
24 |
+
"tailwindcss": "^3.3.3",
|
25 |
+
"typescript": "^5.0.2",
|
26 |
+
"vite": "^4.4.5"
|
27 |
+
}
|
28 |
+
}
|
frontend/src/App.tsx
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useState } from 'react'
|
2 |
+
|
3 |
+
function App() {
|
4 |
+
const [count, setCount] = useState<number>(0)
|
5 |
+
|
6 |
+
return (
|
7 |
+
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
|
8 |
+
<div className="card w-96 bg-base-100 shadow-xl">
|
9 |
+
<div className="card-body">
|
10 |
+
<h2 className="card-title">Flask + React + Docker</h2>
|
11 |
+
<p>Simple proof of concept with Flask backend serving a React frontend.</p>
|
12 |
+
<div className="card-actions justify-center mt-4">
|
13 |
+
<button
|
14 |
+
className="btn btn-primary"
|
15 |
+
onClick={() => setCount((count: number) => count + 1)}
|
16 |
+
>
|
17 |
+
Count is {count}
|
18 |
+
</button>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
</div>
|
22 |
+
</div>
|
23 |
+
)
|
24 |
+
}
|
25 |
+
|
26 |
+
export default App
|
frontend/src/index.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
@tailwind base;
|
2 |
+
@tailwind components;
|
3 |
+
@tailwind utilities;
|
frontend/src/main.tsx
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react'
|
2 |
+
import ReactDOM from 'react-dom/client'
|
3 |
+
import App from './App'
|
4 |
+
import './index.css'
|
5 |
+
|
6 |
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
7 |
+
<React.StrictMode>
|
8 |
+
<App />
|
9 |
+
</React.StrictMode>,
|
10 |
+
)
|
frontend/src/vite-env.d.ts
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
/// <reference types="vite/client" />
|
frontend/tailwind.config.js
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/** @type {import('tailwindcss').Config} */
|
2 |
+
export default {
|
3 |
+
content: [
|
4 |
+
"./index.html",
|
5 |
+
"./src/**/*.{js,ts,jsx,tsx}",
|
6 |
+
],
|
7 |
+
theme: {
|
8 |
+
extend: {},
|
9 |
+
},
|
10 |
+
plugins: [require("daisyui")],
|
11 |
+
daisyui: {
|
12 |
+
themes: ["light"],
|
13 |
+
},
|
14 |
+
}
|
frontend/tsconfig.json
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"compilerOptions": {
|
3 |
+
"target": "ESNext",
|
4 |
+
"useDefineForClassFields": true,
|
5 |
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
6 |
+
"allowJs": false,
|
7 |
+
"skipLibCheck": true,
|
8 |
+
"esModuleInterop": false,
|
9 |
+
"allowSyntheticDefaultImports": true,
|
10 |
+
"strict": true,
|
11 |
+
"forceConsistentCasingInFileNames": true,
|
12 |
+
"module": "ESNext",
|
13 |
+
"moduleResolution": "Node",
|
14 |
+
"resolveJsonModule": true,
|
15 |
+
"isolatedModules": true,
|
16 |
+
"noEmit": true,
|
17 |
+
"jsx": "react-jsx"
|
18 |
+
},
|
19 |
+
"include": ["src"],
|
20 |
+
"references": []
|
21 |
+
}
|
frontend/vite.config.ts
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { defineConfig } from 'vite'
|
2 |
+
import react from '@vitejs/plugin-react'
|
3 |
+
|
4 |
+
// https://vitejs.dev/config/
|
5 |
+
export default defineConfig({
|
6 |
+
plugins: [react()],
|
7 |
+
build: {
|
8 |
+
outDir: 'dist',
|
9 |
+
emptyOutDir: true
|
10 |
+
}
|
11 |
+
})
|
package-lock.json
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "omniseal_dev",
|
3 |
+
"lockfileVersion": 3,
|
4 |
+
"requires": true,
|
5 |
+
"packages": {
|
6 |
+
"": {
|
7 |
+
"devDependencies": {
|
8 |
+
"@types/react": "^19.1.6",
|
9 |
+
"@types/react-dom": "^19.1.6"
|
10 |
+
}
|
11 |
+
},
|
12 |
+
"node_modules/@types/react": {
|
13 |
+
"version": "19.1.6",
|
14 |
+
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz",
|
15 |
+
"integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==",
|
16 |
+
"dev": true,
|
17 |
+
"license": "MIT",
|
18 |
+
"dependencies": {
|
19 |
+
"csstype": "^3.0.2"
|
20 |
+
}
|
21 |
+
},
|
22 |
+
"node_modules/@types/react-dom": {
|
23 |
+
"version": "19.1.6",
|
24 |
+
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
|
25 |
+
"integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
|
26 |
+
"dev": true,
|
27 |
+
"license": "MIT",
|
28 |
+
"peerDependencies": {
|
29 |
+
"@types/react": "^19.0.0"
|
30 |
+
}
|
31 |
+
},
|
32 |
+
"node_modules/csstype": {
|
33 |
+
"version": "3.1.3",
|
34 |
+
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
35 |
+
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
36 |
+
"dev": true,
|
37 |
+
"license": "MIT"
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
package.json
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"devDependencies": {
|
3 |
+
"@types/react": "^19.1.6",
|
4 |
+
"@types/react-dom": "^19.1.6"
|
5 |
+
}
|
6 |
+
}
|