Add build and deploy workflow
All checks were successful
Build and Deploy / build-deploy (push) Successful in 29s
All checks were successful
Build and Deploy / build-deploy (push) Successful in 29s
This commit is contained in:
10
.env.example
Normal file
10
.env.example
Normal file
@@ -0,0 +1,10 @@
|
||||
PUBLIC_WS_URL=ws://localhost:3000/ws
|
||||
PUBLIC_BOX_DRAWING_CHARS=─│┌┐└┘├┤
|
||||
HOST=localhost
|
||||
FE_PORT=5173
|
||||
BE_PORT=3000
|
||||
JWT_SECRET=your-secret-here
|
||||
SIGNUP_SECRET=your-signup-secret-here
|
||||
ADMIN_EMAIL=admin@localhost
|
||||
DB_PATH=packages/be/db.sqlite
|
||||
DATA_DIR=./data
|
||||
47
.gitea/workflows/deploy.yaml
Normal file
47
.gitea/workflows/deploy.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
name: Build and Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: docker:latest
|
||||
volumes:
|
||||
- /opt/todo3:/deploy
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: apk add --no-cache git nodejs
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Copy source to deploy directory
|
||||
run: |
|
||||
rm -rf /deploy/build
|
||||
cp -r . /deploy/build
|
||||
|
||||
- name: Create .env file
|
||||
working-directory: /deploy/build
|
||||
run: |
|
||||
cat > .env << 'EOF'
|
||||
PUBLIC_WS_URL=${{ vars.PUBLIC_WS_URL }}
|
||||
PUBLIC_BOX_DRAWING_CHARS=${{ vars.PUBLIC_BOX_DRAWING_CHARS }}
|
||||
HOST=${{ vars.HOST }}
|
||||
FE_PORT=${{ vars.FE_PORT }}
|
||||
BE_PORT=${{ vars.BE_PORT }}
|
||||
JWT_SECRET=${{ secrets.JWT_SECRET }}
|
||||
SIGNUP_SECRET=${{ secrets.SIGNUP_SECRET }}
|
||||
ADMIN_EMAIL=${{ vars.ADMIN_EMAIL }}
|
||||
DATA_DIR=/opt/todo3/data
|
||||
EOF
|
||||
|
||||
- name: Build and deploy
|
||||
working-directory: /deploy/build
|
||||
run: |
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
|
||||
- name: Cleanup
|
||||
run: rm -rf /deploy/build
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
node_modules
|
||||
.env
|
||||
*.local
|
||||
packages/be/db.sqlite
|
||||
up.sh
|
||||
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
FROM oven/bun:latest AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM base AS deps
|
||||
COPY package.json bun.lockb ./
|
||||
COPY packages/fe/package.json packages/fe/
|
||||
COPY packages/be/package.json packages/be/
|
||||
RUN bun install --frozen-lockfile
|
||||
|
||||
FROM deps AS fe-build
|
||||
COPY packages/fe packages/fe
|
||||
COPY packages/be/src packages/be/src
|
||||
COPY tsconfig.json .
|
||||
ARG PUBLIC_WS_URL
|
||||
ARG PUBLIC_BOX_DRAWING_CHARS
|
||||
ENV PUBLIC_WS_URL=$PUBLIC_WS_URL
|
||||
ENV PUBLIC_BOX_DRAWING_CHARS=$PUBLIC_BOX_DRAWING_CHARS
|
||||
RUN bun run --filter fe build
|
||||
|
||||
FROM base AS frontend
|
||||
WORKDIR /app/packages/fe
|
||||
COPY --from=deps /app/node_modules /app/node_modules
|
||||
COPY --from=fe-build /app/packages/fe/dist ./dist
|
||||
COPY packages/fe/package.json packages/fe/vite.config.ts ./
|
||||
CMD ["bun", "run", "start"]
|
||||
|
||||
FROM base AS backend
|
||||
WORKDIR /app/packages/be
|
||||
COPY --from=deps /app/node_modules /app/node_modules
|
||||
COPY packages/be ./
|
||||
CMD ["bun", "run", "start"]
|
||||
51
README.md
51
README.md
@@ -1,19 +1,50 @@
|
||||
# Elysia with Bun runtime
|
||||
# Todo3
|
||||
|
||||
## Getting Started
|
||||

|
||||
|
||||
To get started with this template, simply paste this command into your terminal:
|
||||
Visually, this is an attempt at replicating lovely TUI aesthetics on the web. It isn't actually rendered in text, but everything is based around the `ch` unit.
|
||||
|
||||
```bash
|
||||
bun create elysia ./elysia-example
|
||||
```
|
||||
Functionally, it's a real-time collaborative todo list, exclusively via WebSockets with optimistic updates. No REST here, not even for authentication. Whether or not this is a good idea remains to be seen.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Frontend**: React, Vite
|
||||
- **Backend**: Elysia, Bun, SQLite
|
||||
- **Real-time**: WebSockets
|
||||
|
||||
## Development
|
||||
|
||||
To start the development server run:
|
||||
|
||||
```bash
|
||||
bun run dev
|
||||
cp .env.example .env
|
||||
# fill in your values
|
||||
```
|
||||
|
||||
Open http://localhost:3000/ with your browser to see the result.
|
||||
### With Docker (recommended)
|
||||
|
||||
```bash
|
||||
bun install
|
||||
docker compose -f docker-compose.dev.yml up
|
||||
```
|
||||
|
||||
Frontend: http://localhost:5173
|
||||
Backend: http://localhost:3000
|
||||
|
||||
## Production
|
||||
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `PUBLIC_WS_URL` | WebSocket URL for frontend |
|
||||
| `PUBLIC_BOX_DRAWING_CHARS` | The 8 characters for box drawing. The default value `─│┌┐└┘├┤` results in boxes that are a bit to nice, you can also try `–\|++++++` for a simpler style |
|
||||
| `HOST` | Allowed host for Vite |
|
||||
| `FE_PORT` | Frontend port (external) |
|
||||
| `BE_PORT` | Backend port (external) |
|
||||
| `JWT_SECRET` | Secret for JWT signing |
|
||||
| `SIGNUP_SECRET` | Required for user registration |
|
||||
| `ADMIN_EMAIL` | Contact email for signup errors |
|
||||
| `DB_PATH` | Path to SQLite database |
|
||||
|
||||
29
docker-compose.dev.yml
Normal file
29
docker-compose.dev.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
name: todo3
|
||||
|
||||
services:
|
||||
fe:
|
||||
image: oven/bun:latest
|
||||
working_dir: /app
|
||||
command: bun run --filter fe dev -- --host
|
||||
ports:
|
||||
- '${FE_PORT:-5173}:5173'
|
||||
volumes:
|
||||
- .:/app
|
||||
environment:
|
||||
HOST: ${HOST:-localhost}
|
||||
PUBLIC_WS_URL: ${PUBLIC_WS_URL:-ws://localhost:3000/ws}
|
||||
PUBLIC_BOX_DRAWING_CHARS: ${PUBLIC_BOX_DRAWING_CHARS:-─│┌┐└┘├┤}
|
||||
|
||||
be:
|
||||
image: oven/bun:latest
|
||||
working_dir: /app
|
||||
command: bun run --filter be dev
|
||||
ports:
|
||||
- '${BE_PORT:-3000}:3000'
|
||||
volumes:
|
||||
- .:/app
|
||||
environment:
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
SIGNUP_SECRET: ${SIGNUP_SECRET}
|
||||
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@localhost}
|
||||
DB_PATH: /app/${DB_PATH}
|
||||
30
docker-compose.yml
Normal file
30
docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
name: todo3
|
||||
|
||||
services:
|
||||
fe:
|
||||
build:
|
||||
context: .
|
||||
target: frontend
|
||||
args:
|
||||
PUBLIC_WS_URL: ${PUBLIC_WS_URL}
|
||||
PUBLIC_BOX_DRAWING_CHARS: ${PUBLIC_BOX_DRAWING_CHARS:-─│┌┐└┘├┤}
|
||||
ports:
|
||||
- '${FE_PORT}:4173'
|
||||
environment:
|
||||
HOST: ${HOST}
|
||||
restart: unless-stopped
|
||||
|
||||
be:
|
||||
build:
|
||||
context: .
|
||||
target: backend
|
||||
ports:
|
||||
- '${BE_PORT}:3000'
|
||||
environment:
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
SIGNUP_SECRET: ${SIGNUP_SECRET}
|
||||
ADMIN_EMAIL: ${ADMIN_EMAIL}
|
||||
DB_PATH: /data/db.sqlite
|
||||
volumes:
|
||||
- ${DATA_DIR:-./data}:/data
|
||||
restart: unless-stopped
|
||||
@@ -1,4 +0,0 @@
|
||||
JWT_SECRET=FOOBAR
|
||||
SIGNUP_SECRET=FOOBAR
|
||||
ADMIN_EMAIL=foo@bar.com
|
||||
PORT=3000
|
||||
@@ -1,3 +1,3 @@
|
||||
import { Database } from 'bun:sqlite';
|
||||
|
||||
export const db = new Database('db.sqlite');
|
||||
export const db = new Database(process.env.DB_PATH ?? 'db.sqlite');
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#PUBLIC_BOX_DRAWING_CHARS=─│┌┐└┘├┤
|
||||
PUBLIC_BOX_DRAWING_CHARS=-|++++++
|
||||
PUBLIC_WS_URL=wss://echo.websocket.org
|
||||
HOST=example.org
|
||||
PORT=5173
|
||||
@@ -3,17 +3,6 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
as="style"
|
||||
href="https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Todo 3.0</title>
|
||||
</head>
|
||||
|
||||
BIN
packages/fe/public/fonts/OGCourier-Bold.woff2
Normal file
BIN
packages/fe/public/fonts/OGCourier-Bold.woff2
Normal file
Binary file not shown.
BIN
packages/fe/public/fonts/OGCourier-BoldItalic.woff2
Normal file
BIN
packages/fe/public/fonts/OGCourier-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
packages/fe/public/fonts/OGCourier-Italic.woff2
Normal file
BIN
packages/fe/public/fonts/OGCourier-Italic.woff2
Normal file
Binary file not shown.
BIN
packages/fe/public/fonts/OGCourier.woff2
Normal file
BIN
packages/fe/public/fonts/OGCourier.woff2
Normal file
Binary file not shown.
@@ -1,5 +1,33 @@
|
||||
@font-face {
|
||||
font-family: 'OGCourier';
|
||||
src: url('/fonts/OGCourier.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'OGCourier';
|
||||
src: url('/fonts/OGCourier-Bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'OGCourier';
|
||||
src: url('/fonts/OGCourier-Italic.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'OGCourier';
|
||||
src: url('/fonts/OGCourier-BoldItalic.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: 'Courier Prime', monospace;
|
||||
font-family: 'OGCourier', monospace;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -13,7 +13,6 @@ export default ({ mode }: { mode: string }) => {
|
||||
},
|
||||
preview: {
|
||||
allowedHosts: [env.HOST!],
|
||||
port: Number(env.PORT!),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Reference in New Issue
Block a user