Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cpluspatch/web-business
A customizable CMS written in Vue with a dynamic block system
https://github.com/cpluspatch/web-business
cms nuxt typescript vue
Last synced: 19 days ago
JSON representation
A customizable CMS written in Vue with a dynamic block system
- Host: GitHub
- URL: https://github.com/cpluspatch/web-business
- Owner: CPlusPatch
- License: gpl-3.0
- Created: 2023-07-15T03:12:00.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2023-11-16T19:33:25.000Z (about 1 year ago)
- Last Synced: 2024-12-06T17:26:27.583Z (2 months ago)
- Topics: cms, nuxt, typescript, vue
- Language: Vue
- Homepage: https://cpluspatch.com
- Size: 12 MB
- Stars: 6
- Watchers: 0
- Forks: 0
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: COPYING
Awesome Lists containing this project
README
# CPlusPatch CMS
A fast, sleek and beautiful website + full content management system developed with NuxtJS.
It is designed to be minimal but efficient, secure and lightweight.
CPlusPatch CMS is a customizable system for making blogs and personal pages with a dynamic Vue-based templating engine. This is a project in **beta**, and as such should be treated as unstable.
## Requirements- A system that can run Node.js (Linux is HEAVILY recommended), or Docker on Linux
- An S3 or S3 compatible bucket (for example, Cloudflare R2)## Downloading and running
You may use the `docker-compose.yml` file included in this repository to bootstrap a working environment very fast.
Alternatively, download and install manually:
```bash
git clone https://codeberg.org/CPlusPatch/web-business.git
cd web-business
pnpm install
```Then, fill out .env with credentials for the S3 or S3-compatible bucket (such as Cloudflare R2, which I am using) and for PostgreSQL.
```bash
cp .env.example .env
```For the CDN URL, do not include a trailing slash at the end.
Don't forget to rename `config/config.example.toml` to `config.toml`!
## Building manually
```bash
pnpm build # Bundles project into JS files# EITHER
pnpm preview # For testing
pm2 start ecosystem.config.js # For production deployment with PM2
```## Administration
### Adding new users (for now)
**NOTE: These instructions are temporary, an admin panel for adding users is coming soon**
You may use the following JS scripts to generate a hashed password with Node's `crypto` library:
```js
import { randomBytes, pbkdf2 } from "crypto";export function createSalt(length = 128) {
return randomBytes(length).toString("base64");
}export function createPasswordHash(
password,
salt = "",
iterations = 10000
) {
return new Promise((resolve, reject) => {
pbkdf2(password, salt, iterations, 100, "sha256", (err, derivedKey) => {
if (err) return reject(err);
return resolve(`${derivedKey.toString("hex")}:${salt}`);
});
});
}
```To use it, run `createSalt` to generate a random salt, then run `createPasswordHash("your password here", salt)` to generate a new salted password.
Passwords are stored as `hash:salt` in the database, and `createPasswordHash` outputs this format.
To continue, you will need some kind of PostgreSQL browser and a working instance of the web app: more administration tools are coming soon.
Open to the `user` table, and insert the following row:
```
┌────────────┬───────────────────┬───────────────┬──────────────────────┐
│ username │ display_name │ oauthAccounts │ password │
├────────────┼───────────────────┼───────────────┼──────────────────────┤
│ A username │ New display name │ [] │ │
└────────────┴───────────────────┴───────────────┴──────────────────────┘
```All the other fields may be left blank or will be generated automatically. If the user needs to be an admin, that is a creator of posts, insert this row instead:
```
┌────────────┬───────────────────┬───────────────┬──────────────────────┬───────┐
│ username │ display_name │ oauthAccounts │ password │ role │
├────────────┼───────────────────┼───────────────┼──────────────────────┼───────┤
│ A username │ New display name │ [] │ │ admin │
└────────────┴───────────────────┴───────────────┴──────────────────────┴───────┘```
You can save and login with your new credentials now.
## Scripts for development
### Images
Convert all JPEG images to WebP (uses ImageMagick)
```bash
magick mogrify -format webp *.jpeg
```
Convert all JPEG images to WebP (uses ImageMagick)Resize all images to 250x250 (when adding languages to `/public/static/languages/`)
```bash
mogrify -path . -auto-orient -thumbnail 250x *.png
```## Writing custom templates
To add custom templates to the CMS block system, open the `templates/` directory, then create two files inside a category folder: `TemplateName.vue` and `TemplateName.json`. You may also create new folders, the location doesn't matter as long as it's inside `templates/`.
Inside the `.vue` file you may write a new Vue component. You will need to add this block of code:
```vue
defineProps<{
editable: boolean;
// You may add arbitrary props here
}>();```
You may use TypeScript and all classes provided by [https://unocss.dev/](UnoCSS), as well as NuxtJS 3.6 utilities and any package that is included in `package.json` (such as `nuxt-img`).Here is an example for a big hero header:
```vue
defineProps<{
imageMain?: string;
editable: boolean;
}>();
```
It is recommended that you look at other files inside `templates` to get a hang of the syntax.
### Syntax for the metadata
Once your component is written, you may add your template metadata to `TemplateName.json`, like this:
```json
{
"category": "heroes",
"name": "BigHero",
"displayName": "Big Banner",
"description": "Big banner for showing off an image",
"inputs": {
"image-main": "string"
},
"defaults": {
"image-main": ""
}
}
```This will allow you to auto-generate the configuration panel for your component.
The syntax for `inputs` goes as follow:
**Input types**
```json
"inputs": {
"header-image": "image",
"large-text": "paragraph",
"text-input": "string",
"invert-order": "boolean",
}
```**Arrays**
Arrays can be declared with an array of a single object, which will be the type of all objects in the array. You can nest arrays inside arrays at will.
```json
"inputs": {
"grid": [
{
"id": "string",
"tags": [
{
"id": "string",
"name": "string",
"color": "string",
"text-color": "string"
}
],
"description": "string",
"name": "string",
"href": "string"
}
]
},
```> **Note**: These `input` attributes will be passed to the Vue component as props, so their name will be converted to camelCase (e.g. `image-main` will be converted to `imageMain`)
## Attributions
I will add more attributions when I find the image sources (mostly logos)
Evan You, https://github.com/yyx990803, CC BY 4.0
, via Wikimedia Commons, for the VueJS logo## Internals
Data is stored inside a PostgreSQL database.
When uploading images, they are converted to WebP inside the browser itself before upload.
---
Licensed under GPLv3. Made with 💕