diff --git a/backend/main.py b/backend/main.py
index e392f81..e1d3abf 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,4 +1,5 @@
from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
import models
from database import engine
@@ -6,6 +7,14 @@ from routers import auth, forum
app = FastAPI()
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=['*'],
+ allow_credentials=False,
+ allow_methods=['GET', 'POST'],
+ allow_headers=['*']
+)
+
models.Base.metadata.create_all(bind=engine)
app.include_router(forum.router)
diff --git a/docker-compose.yml b/docker-compose.yml
index 424b334..36dc28d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -4,6 +4,16 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
+ ports:
+ - '8001:8000'
+ restart: unless-stopped
+
+ frontend:
+ build:
+ context: ./frontend
+ dockerfile: Dockerfile
ports:
- '8000:8000'
restart: unless-stopped
+ depends_on:
+ - backend
\ No newline at end of file
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..9f11b75
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1 @@
+.idea/
diff --git a/frontend/Dockerfile b/frontend/Dockerfile
new file mode 100644
index 0000000..4a80c35
--- /dev/null
+++ b/frontend/Dockerfile
@@ -0,0 +1,13 @@
+FROM node:alpine
+
+WORKDIR /app
+COPY ./app/package.json /app/package.json
+RUN npm install
+
+COPY ./app /app
+RUN npm run build
+
+RUN npm install -g serve
+
+EXPOSE 3000
+CMD ["serve", "-s", "--no-clipboard", "build"]
diff --git a/frontend/app/.gitignore b/frontend/app/.gitignore
new file mode 100644
index 0000000..4d29575
--- /dev/null
+++ b/frontend/app/.gitignore
@@ -0,0 +1,23 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/frontend/app/package.json b/frontend/app/package.json
new file mode 100644
index 0000000..9c11af8
--- /dev/null
+++ b/frontend/app/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "forum",
+ "version": "0.1.0",
+ "private": true,
+ "dependencies": {
+ "@testing-library/jest-dom": "^5.17.0",
+ "@testing-library/react": "^13.4.0",
+ "@testing-library/user-event": "^13.5.0",
+ "axios": "^1.6.8",
+ "bulma": "^1.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-scripts": "5.0.1",
+ "web-vitals": "^2.1.4"
+ },
+ "scripts": {
+ "start": "react-scripts start",
+ "build": "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"
+ ]
+ }
+}
diff --git a/frontend/app/public/favicon.ico b/frontend/app/public/favicon.ico
new file mode 100644
index 0000000..a11777c
Binary files /dev/null and b/frontend/app/public/favicon.ico differ
diff --git a/frontend/app/public/index.html b/frontend/app/public/index.html
new file mode 100644
index 0000000..aa069f2
--- /dev/null
+++ b/frontend/app/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ React App
+
+
+
+
+
+
+
diff --git a/frontend/app/public/logo192.png b/frontend/app/public/logo192.png
new file mode 100644
index 0000000..fc44b0a
Binary files /dev/null and b/frontend/app/public/logo192.png differ
diff --git a/frontend/app/public/logo512.png b/frontend/app/public/logo512.png
new file mode 100644
index 0000000..a4e47a6
Binary files /dev/null and b/frontend/app/public/logo512.png differ
diff --git a/frontend/app/public/manifest.json b/frontend/app/public/manifest.json
new file mode 100644
index 0000000..080d6c7
--- /dev/null
+++ b/frontend/app/public/manifest.json
@@ -0,0 +1,25 @@
+{
+ "short_name": "React App",
+ "name": "Create React App Sample",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "64x64 32x32 24x24 16x16",
+ "type": "image/x-icon"
+ },
+ {
+ "src": "logo192.png",
+ "type": "image/png",
+ "sizes": "192x192"
+ },
+ {
+ "src": "logo512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/frontend/app/public/robots.txt b/frontend/app/public/robots.txt
new file mode 100644
index 0000000..e9e57dc
--- /dev/null
+++ b/frontend/app/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/frontend/app/src/App.js b/frontend/app/src/App.js
new file mode 100644
index 0000000..45f7602
--- /dev/null
+++ b/frontend/app/src/App.js
@@ -0,0 +1,41 @@
+import 'bulma/css/bulma.css'
+import {useEffect, useState} from "react";
+import axios from "axios";
+import PostList from "./components/Post/PostList";
+
+function App() {
+ const [postList, setPostsList] = useState([]);
+
+ const fetchPosts = async () => {
+ await axios.get("http://localhost:8000/catalog")
+ .then((response) => { setPostsList(response.data)})
+ }
+
+ useEffect(() => {
+ fetchPosts();
+ }, []);
+
+ async function handleClickRefresh() {
+ await fetchPosts();
+ }
+
+ return (
+ <>
+
+
+
+
Singleboard Forum App
+
+
+
+
+ >
+ );
+}
+
+export default App;
\ No newline at end of file
diff --git a/frontend/app/src/components/Post/PostList.js b/frontend/app/src/components/Post/PostList.js
new file mode 100644
index 0000000..5105770
--- /dev/null
+++ b/frontend/app/src/components/Post/PostList.js
@@ -0,0 +1,19 @@
+import PostShow from "./PostShow";
+
+function PostList({posts}) {
+ const renderedPosts = posts.map((post, key) => {
+ return
+ })
+
+ return (
+ <>
+
+ >
+ );
+}
+
+export default PostList
\ No newline at end of file
diff --git a/frontend/app/src/components/Post/PostShow.js b/frontend/app/src/components/Post/PostShow.js
new file mode 100644
index 0000000..2e983ea
--- /dev/null
+++ b/frontend/app/src/components/Post/PostShow.js
@@ -0,0 +1,14 @@
+function PostShow({title, content, post_id}) {
+ return (
+ <>
+
+
{title}
+
{content}
+
+
0 replies
+
+ >
+ );
+}
+
+export default PostShow;
\ No newline at end of file
diff --git a/frontend/app/src/index.js b/frontend/app/src/index.js
new file mode 100644
index 0000000..23ffbde
--- /dev/null
+++ b/frontend/app/src/index.js
@@ -0,0 +1,8 @@
+import React from "react";
+import ReactDOM from "react-dom/client"
+import App from "./App";
+
+const el = document.getElementById("root");
+const root = ReactDOM.createRoot(el)
+
+root.render()
\ No newline at end of file
diff --git a/frontend/conf/nginx.conf b/frontend/conf/nginx.conf
new file mode 100644
index 0000000..0e66c15
--- /dev/null
+++ b/frontend/conf/nginx.conf
@@ -0,0 +1,22 @@
+events {
+ worker_connections 1024;
+}
+
+http {
+ server {
+ listen 8000 default_server;
+ listen [::]:8000 default_server;
+
+ root /app;
+ index index.html;
+ server_name _;
+
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ location /api {
+ proxy_pass http://backend:8000/;
+ }
+ }
+}
\ No newline at end of file