Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions example6-vue-robyn-multistage/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Stage 1: Build the frontend
# The platform is hardcoded because bun does not support armv7. The result of this build is architecture agnostic.
FROM --platform=amd64 oven/bun:1 AS frontend
WORKDIR /app

# Copy necessary files for bun install
COPY bun.lock package.json vite.config.js ./
RUN bun install

# Copy frontend files for build
COPY ./src ./src
COPY index.html ./
RUN bun run build

# Stage 2: Build the backend
FROM python:3.12-slim-bookworm AS backend
WORKDIR /app

RUN apt update && apt install -y curl

# Install UV
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
# Necessary for running uv sync
ENV PATH="/root/.local/bin/:$PATH"

COPY pyproject.toml uv.lock ./
RUN uv sync

COPY --from=frontend /app ./
COPY . .

ENV PATH="/app/.venv/bin:$PATH" \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

LABEL version="1.0.0"
LABEL permissions='{\
"ExposedPorts": {\
"80/tcp": {}\
},\
"HostConfig": {\
"PortBindings": {\
"80/tcp": [\
{\
"HostPort": ""\
}\
]\
}\
}\
}'
LABEL authors='[\
{\
"name": "Nicole Schmidt",\
"email": "[email protected]"\
}\
]'
LABEL company='{\
"about": "",\
"name": "Blue Robotics",\
"email": "[email protected]"\
}'
LABEL type="example"
LABEL readme='https://raw.githubusercontent.com/nicoschmdt/BlueOS-examples/{tag}/example6-vue-robyn-multistage/README.md'
LABEL links='{\
"website": "https://github.com/nicoschmdt/BlueOS-examples/",\
"support": "https://github.com/nicoschmdt/BlueOS-examples/"\
}'
LABEL requirements="core >= 1.3"


CMD ["python", "-m", "main"]
24 changes: 24 additions & 0 deletions example6-vue-robyn-multistage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Vue3 Webpage extension

This template uses Robyn as a backend API which serves the Vue3 frontend.

## Build

Enable qemu static support with a docker

```
docker buildx create --name multiarch --driver docker-container --use
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
```

Then build it:

`docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 . -t YOURDOCKERHUBUSER/YOURDOCKERHUBREPO:latest --output type=registry
`

Then pull it in blueos:

```
red-pill
sudo docker run -d --net=host --name=blueos-example6 --restart=unless-stopped YOURDOCKERHUBUSER/YOURDOCKERHUBREPO:latest
```
444 changes: 444 additions & 0 deletions example6-vue-robyn-multistage/bun.lock

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions example6-vue-robyn-multistage/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example 6</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
29 changes: 29 additions & 0 deletions example6-vue-robyn-multistage/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from robyn import Robyn
from robyn.responses import serve_file, serve_html

app = Robyn(__name__)

@app.get("/hello")
async def root():
return "Hello from the Robyn backend!"

@app.get("/")
async def root():
return serve_html("dist/index.html")

@app.get("/register_service")
def register_service():
return serve_file("src/register_service")

@app.get("/assets/:path")
async def serve_static_assets(path_params):
path = path_params["path"]
return serve_file(f"dist/assets/{path}")


def main():
app.start(host="0.0.0.0", port=8123)


if __name__ == "__main__":
main()
23 changes: 23 additions & 0 deletions example6-vue-robyn-multistage/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "example6-vue-robyn-multistage",
"version": "0.0.0",
"private": true,
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.5.18",
"axios": "^1.7.9"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"vite": "^7.0.6",
"vite-plugin-vue-devtools": "^8.0.0"
}
}
9 changes: 9 additions & 0 deletions example6-vue-robyn-multistage/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
name = "example6-vue-robyn-multistage"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"robyn>=0.72.0",
]
62 changes: 62 additions & 0 deletions example6-vue-robyn-multistage/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<template>
<div class="container">
<div class="title">Vue 3 + Robyn + Multistage Docker Build Extension</div>

<div class="description">The following button performs a GET request to the backend:</div>
<div>
<button class="button" @click="doRequest">Click me</button>
</div>
<div>{{ response }}</div>
</div>
</template>

<script>
import axios from 'axios'

export default {
name: 'App',
data() {
return {
response: ''
}
},
methods: {
async doRequest() {
const answer = await axios.get('/hello')
this.response = answer.data
}
}
}
</script>

<style scoped>
.container {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding-top: 20px;
}

.title {
font-size: 36px;
font-weight: bold;
margin-bottom: 20px;
}

.description {
font-size: 18px;
margin-bottom: 20px;
align-self: flex-start;
}

.button {
font-size: 15px;
padding: 5px 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
align-items: center;
}
</style>
86 changes: 86 additions & 0 deletions example6-vue-robyn-multistage/src/assets/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;

--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;

--vt-c-indigo: #2c3e50;

--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);

--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}

/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);

--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);

--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);

--section-gap: 160px;
}

@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);

--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);

--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}

*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}

body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
36 changes: 36 additions & 0 deletions example6-vue-robyn-multistage/src/assets/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@import './base.css';

#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}

a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
}

@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}

@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}

#app {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 2rem;
}
}
6 changes: 6 additions & 0 deletions example6-vue-robyn-multistage/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
9 changes: 9 additions & 0 deletions example6-vue-robyn-multistage/src/register_service
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name":"Example 6: Vue3 + Robyn",
"description":"Example Extension",
"icon":"mdi-heart-cog",
"company":"Blue Robotics",
"version":"1.0.0",
"webpage":"https://example.com",
"api":""
}
Loading