Skip to content

Commit b5f88ad

Browse files
committed
Initial project
1 parent 9f6f6cf commit b5f88ad

68 files changed

Lines changed: 21943 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Node.js
2+
node_modules
3+
npm-debug.log
4+
yarn-debug.log
5+
yarn-error.log
6+
7+
# Build outputs
8+
.nuxt
9+
.output
10+
dist
11+
12+
# Version control
13+
.git
14+
.github
15+
.gitignore
16+
.vscode
17+
18+
# Editor directories and files
19+
.vscode
20+
.idea
21+
*.suo
22+
*.ntvs*
23+
*.njsproj
24+
*.sln
25+
*.sw?
26+
27+
# Environment variables
28+
.env
29+
.env.*
30+
!.env.example
31+
32+
# Logs
33+
logs
34+
*.log
35+
36+
# System Files
37+
.DS_Store
38+
Thumbs.db
39+
40+
# Docker files
41+
Dockerfile
42+
docker-compose.yml
43+
.dockerignore
44+
45+
# Other unnecessary files
46+
README.md
47+
LICENSE
48+
.history
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Docker Build and Publish
2+
3+
on:
4+
push:
5+
tags: ["v*.*.*"]
6+
7+
env:
8+
REGISTRY: docker.io
9+
IMAGE_NAME: ${{ github.repository }}
10+
11+
jobs:
12+
build-and-push:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
packages: write
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
25+
- name: Login to Docker Hub
26+
uses: docker/login-action@v3
27+
with:
28+
username: ${{ secrets.DOCKERHUB_USERNAME }}
29+
password: ${{ secrets.DOCKERHUB_TOKEN }}
30+
31+
- name: Extract metadata (tags, labels) for Docker
32+
id: meta
33+
uses: docker/metadata-action@v5
34+
with:
35+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
36+
tags: |
37+
type=semver,pattern={{version}}
38+
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
39+
labels: |
40+
maintainer=Flexson Team
41+
org.opencontainers.image.title=Flexson
42+
org.opencontainers.image.description=The Powerful JSON Data Management Platform
43+
org.opencontainers.image.vendor=Flexson Team
44+
org.opencontainers.image.licenses=MIT
45+
46+
- name: Build and push Docker image
47+
uses: docker/build-push-action@v5
48+
with:
49+
context: .
50+
push: ${{ github.event_name != 'pull_request' }}
51+
tags: ${{ steps.meta.outputs.tags }}
52+
labels: ${{ steps.meta.outputs.labels }}
53+
cache-from: type=gha
54+
cache-to: type=gha,mode=max
55+
56+
- name: Create temporary README with absolute URLs
57+
if: github.event_name != 'pull_request'
58+
run: |
59+
# Create a temporary README with absolute URLs for images
60+
sed 's|<img src="app/assets/logo.png" width="120" />|<br>|g' README.md > README.docker.md
61+
62+
- name: Update Docker Hub Overview
63+
if: github.event_name != 'pull_request'
64+
uses: peter-evans/dockerhub-description@v3
65+
with:
66+
username: ${{ secrets.DOCKERHUB_USERNAME }}
67+
password: ${{ secrets.DOCKERHUB_TOKEN }}
68+
repository: ${{ env.IMAGE_NAME }}
69+
readme-filepath: ./README.docker.md
70+
short-description: "The Powerful JSON Data Management Platform"

.gitignore

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Nuxt dev/build outputs
2+
.output
3+
.data
4+
.nuxt
5+
.nitro
6+
.cache
7+
.vscode
8+
dist
9+
10+
# Node dependencies
11+
node_modules
12+
13+
# Logs
14+
logs
15+
*.log
16+
17+
# Misc
18+
.DS_Store
19+
.fleet
20+
.idea
21+
22+
# Local env files
23+
.env
24+
.env.*
25+
!.env.example

Dockerfile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
FROM node:22-alpine AS build
2+
WORKDIR /app
3+
4+
RUN corepack enable
5+
6+
# Copy package.json and your lockfile, here we add pnpm-lock.yaml for illustration
7+
COPY package*.json ./
8+
9+
# Install dependencies
10+
RUN pnpm i
11+
12+
# Copy the entire project
13+
COPY . ./
14+
15+
# Build the project
16+
RUN pnpm run build
17+
18+
# Build Stage 2
19+
20+
FROM node:22-alpine
21+
WORKDIR /app
22+
23+
# Only `.output` folder is needed from the build stage
24+
COPY --from=build /app/.output/ ./
25+
26+
# Change the port and host
27+
ENV PORT 80
28+
ENV HOST 0.0.0.0
29+
30+
EXPOSE 80
31+
32+
CMD ["node", "/app/server/index.mjs"]

README.md

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,168 @@
1-
# flexson
1+
<h2 align="center">
2+
<div>
3+
<a style="color:5dc4f3" href="https://github.com/ambyte/flexson">
4+
<img src="app/assets/logo.png" width="120" />
5+
<br>
6+
Flexson
7+
</a>
8+
</div>
9+
<br>
10+
The Powerful JSON Data Management Platform
11+
</h2>
12+
13+
<p align="center">
14+
A comprehensive platform for efficient JSON file management with robust authentication, collaborative group workspaces, secure API access, and versatile data endpoints. Flexson streamlines creating, organizing, and sharing JSON data through an intuitive interface while maintaining enterprise-level security and access controls.
15+
</p>
16+
17+
# Features
18+
19+
- 📁 Create, view, edit, and delete JSON files
20+
- 🌐 Public and protected REST API for get and save files
21+
- 🔍 Organize files into groups
22+
- 🔄 Real-time JSON validation and formatting
23+
- 🔐 JWT authentication (register, login, token refresh)
24+
- 🔑 API key generation and management
25+
- 🛡️ Flexible group access (public write, protected by API key)
26+
- 🖥️ Modern UI with Vuetify
27+
28+
# Quick Start
29+
30+
### Local
31+
32+
1. Clone the repository and install dependencies (`npm install` or `yarn install`)
33+
2. Start the development server: `npm run dev`
34+
3. The app will be available at http://localhost:3000
35+
36+
### Docker
37+
38+
- Use `docker-compose up -d` to start in containers
39+
- For production: `docker build -t flexson .` and `docker run -d -p 80:80 --name flexson flexson`
40+
41+
### Docker Hub
42+
43+
```
44+
services:
45+
flexson:
46+
image: ambyte/flexson:latest
47+
container_name: flexson-app
48+
restart: unless-stopped
49+
ports:
50+
- "8123:80"
51+
environment:
52+
- APP_JWT_SECRET=your_super_secure_jwt_secret_key_change_in_production
53+
- APP_MONGO_URI=mongodb://admin:password@mongo:27017
54+
- APP_MONGO_DB=flexsondb
55+
- APP_ADMIN_USERNAME=admin
56+
- APP_ADMIN_PASSWORD=1password
57+
- APP_PUBLIC_DISABLE_REGISTRATION=true
58+
- APP_PUBLIC_BASE_URL=https://yourwebaddress.com
59+
depends_on:
60+
- mongo
61+
networks:
62+
- app-network
63+
64+
mongo:
65+
image: mongo:latest
66+
container_name: flexson-db
67+
restart: unless-stopped
68+
ports:
69+
- "27027:27017"
70+
environment:
71+
MONGO_INITDB_ROOT_USERNAME: admin
72+
MONGO_INITDB_ROOT_PASSWORD: password
73+
volumes:
74+
- mongodb_data:/data/db
75+
networks:
76+
- app-network
77+
78+
volumes:
79+
mongodb_data:
80+
81+
networks:
82+
app-network:
83+
driver: bridge
84+
85+
```
86+
87+
# Architecture
88+
89+
### Frontend
90+
91+
- **Nuxt 3** (Vue 3, TypeScript)
92+
- **Pinia** for state management
93+
- **Vuetify** UI components
94+
- **Components**: JSON editor, file forms, theme toggle, etc.
95+
96+
### Backend
97+
98+
- **Nuxt server routes** (TypeScript)
99+
- **MongoDB** for storing users, files, groups, API keys
100+
- **JWT** for authentication and authorization
101+
- **API keys** for protected group access
102+
- **Public API** for submitting data to groups with public write enabled
103+
104+
# API
105+
106+
If the group is labeled protected, then you must specify the x-api-key with the previously created API key in the request header.
107+
108+
```
109+
x-api-key: "your_api_key"
110+
```
111+
112+
### Public & Protected Group API
113+
114+
- `GET /api/data/{userslug}/{groupslug}` — Get all files in a group (API key required if protected)
115+
- `GET /api/data/{userslug}/{groupslug}/{fileslug}` — Get a specific file from a group (API key required if protected)
116+
- `POST /api/data/{userslug}/{groupslug}` — Submit new JSON or update existing file in a group (if public write is enabled, API key required if protected)
117+
118+
#### Example: Get all files in a group (protected)
119+
120+
```js
121+
fetch("http://localhost:3000/api/data/someuser/team-reports", {
122+
headers: { "X-API-Key": "<your_api_key>" },
123+
})
124+
.then((res) => res.json())
125+
.then(console.log);
126+
```
127+
128+
#### Example: Get a specific file from a group (protected)
129+
130+
```js
131+
fetch("http://localhost:3000/api/data/someuser/team-reports/somefile", {
132+
headers: { "X-API-Key": "<your_api_key>" },
133+
})
134+
.then((res) => res.json())
135+
.then(console.log);
136+
```
137+
138+
### Example: Public submission
139+
140+
```js
141+
const data = {
142+
name: "Sample Report",
143+
slug: "sample-report" // optionally
144+
content: { title: "Weekly", items: [1, 2, 3] },
145+
description: "Weekly report", // optionally
146+
};
147+
fetch("http://localhost:3000/api/data/someuser/team-reports", {
148+
method: "POST",
149+
headers: { "Content-Type": "application/json" },
150+
body: JSON.stringify(data),
151+
})
152+
.then((res) => res.json())
153+
.then(console.log);
154+
```
155+
156+
#### Submission JSON response
157+
158+
```json
159+
{
160+
"success": true,
161+
"message": "Data saved successfully",
162+
"fileUrl": "http://localhost:3000/api/data/someuser/team-reports/sample-report"
163+
}
164+
```
165+
166+
# License
167+
168+
MIT License

app/app.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<template>
2+
<NuxtLayout>
3+
<NuxtPage />
4+
</NuxtLayout>
5+
</template>
6+
<script setup lang="ts">
7+
import { useNuxtApp } from 'nuxt/app'
8+
import { useTheme } from 'vuetify'
9+
import { onMounted } from 'vue'
10+
11+
const theme = useTheme()
12+
13+
onMounted(() => {
14+
const savedTheme = localStorage.getItem('theme')
15+
if (savedTheme) {
16+
theme.global.name.value = savedTheme
17+
}
18+
})
19+
20+
const nuxtApp = useNuxtApp();
21+
if (nuxtApp.$client) {
22+
nuxtApp.hooks.hook('link:prefetch', () => {
23+
return Promise.resolve();
24+
});
25+
}
26+
</script>

app/assets/logo.png

59.9 KB
Loading

0 commit comments

Comments
 (0)