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 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
+ }