Compare commits

..

No commits in common. "d1a6b17920c5a0f75f1a3e5fdf9417e524627f09" and "676ececfadd00ff22db6f59f7f21f3df77e25ffd" have entirely different histories.

19 changed files with 7 additions and 304 deletions

View File

@ -1,12 +1,6 @@
# Singleboard Forum
A 4ch ripoff, coded as an exercise in learning full stack development with React
and FastAPI.
# Forum App with FastAPI
Model is after 4chan
## Demo
Start the Docker containers:
```
docker compose up -d
```
Interact with the backend API to add some posts by browsing to http://localhost:8000/docs,
then browse to the frontend at http://localhost:3000.
Board: has threads, unique counter for posts
Thread: Collection of related posts
Post: post_id, thread_id, title, content

View File

@ -1,5 +1,4 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import models
from database import engine
@ -7,14 +6,6 @@ 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)

View File

@ -7,13 +7,3 @@ services:
ports:
- '8000:8000'
restart: unless-stopped
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- '3000:3000'
restart: unless-stopped
depends_on:
- backend

1
frontend/.gitignore vendored
View File

@ -1 +0,0 @@
.idea/

View File

@ -1,13 +0,0 @@
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"]

View File

@ -1,22 +1,4 @@
# Forum Frontend
The frontend for the forum is written in React.
Should be extremely simple to start with no styling.
**Note**: Before running, update the `apiUrl` in `app/src/App.js` to point your backend.
## Development
To start the frontend in development mode and serve on http://localhost:3000:
```shell
npm run start
```
## Production
```shell
# Install serve
npm install -g serve
# Build for production
npm run build
# Serve
serve -s --no-clipboard build
```
Node.js with a nice framework should be the ultimate goal, but could just do simple HTML and JS by hand for now.

View File

@ -1,23 +0,0 @@
# 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*

View File

@ -1,40 +0,0 @@
{
"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"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,43 +0,0 @@
<!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="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -1,25 +0,0 @@
{
"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"
}

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,43 +0,0 @@
import 'bulma/css/bulma.css'
import {useEffect, useState} from "react";
import axios from "axios";
import PostList from "./components/Post/PostList";
const apiUrl = "http://localhost:8000";
function App() {
const [postList, setPostsList] = useState([]);
const fetchPosts = async () => {
await axios.get(apiUrl + "/catalog")
.then((response) => { setPostsList(response.data)})
}
useEffect(() => {
fetchPosts();
}, []);
async function handleClickRefresh() {
await fetchPosts();
}
return (
<>
<div className="container">
<section className="hero is-info">
<div className="hero-body">
<p className="title">Singleboard Forum App</p>
</div>
</section>
<div className="section">
<div className="container" style={{marginBottom: "50px"}}>
<button className="button" onClick={handleClickRefresh}>Refresh Posts</button>
</div>
<PostList posts={postList}/>
</div>
</div>
</>
);
}
export default App;

View File

@ -1,19 +0,0 @@
import PostShow from "./PostShow";
function PostList({posts}) {
const renderedPosts = posts.map((post, key) => {
return <PostShow title={post.title} content={post.content} key={key}/>
})
return (
<>
<div className="container">
<div className="columns is-multiline">
{renderedPosts}
</div>
</div>
</>
);
}
export default PostList

View File

@ -1,14 +0,0 @@
function PostShow({title, content, post_id}) {
return (
<>
<div className="column is-4">
<h1 className="is-size-5 has-text-weight-bold">{title}</h1>
<p>{content}</p>
<br />
<p className="is-italic">0 replies</p>
</div>
</>
);
}
export default PostShow;

View File

@ -1,8 +0,0 @@
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(<App />)

View File

@ -1,22 +0,0 @@
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/;
}
}
}