generated from autonomic-cooperative/astro-payload-template
Initial commit
This commit is contained in:
commit
d07472434f
54
.drone.yml
Normal file
54
.drone.yml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: publish pipeline
|
||||||
|
steps:
|
||||||
|
- name: publish astro container
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
username: 3wordchant
|
||||||
|
password:
|
||||||
|
from_secret: git_autonomic_zone_token_3wc
|
||||||
|
# NOTE: edit this if you want your image called something else
|
||||||
|
repo: git.autonomic.zone/DRONE_REPO-astro
|
||||||
|
auto_tag: true
|
||||||
|
registry: git.autonomic.zone
|
||||||
|
context: astro
|
||||||
|
dockerfile: astro/Dockerfile
|
||||||
|
- name: publish payload container
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
username: 3wordchant
|
||||||
|
password:
|
||||||
|
from_secret: git_autonomic_zone_token_3wc
|
||||||
|
# NOTE: edit this if you want your image called something else
|
||||||
|
repo: git.autonomic.zone/DRONE_REPO-payload
|
||||||
|
auto_tag: true
|
||||||
|
registry: git.autonomic.zone
|
||||||
|
context: payload
|
||||||
|
dockerfile: payload/Dockerfile
|
||||||
|
target: prod
|
||||||
|
# See https://docz.autonomic.zone/doc/setting-up-auto-deployment-using-drone-I4j2onjaKT
|
||||||
|
- name: deploy stack
|
||||||
|
image: git.coopcloud.tech/coop-cloud/stack-ssh-deploy:latest
|
||||||
|
settings:
|
||||||
|
stack: <FILL IN e.g. subdomain_domain_tld>
|
||||||
|
host: <FILL IN HOST HERE>
|
||||||
|
deploy_key:
|
||||||
|
from_secret: drone_ssh_<FILL IN>
|
||||||
|
environment:
|
||||||
|
DOMAIN: <FILL IN>
|
||||||
|
STACK_NAME: <FILL IN e.g. subdomain_domain_tld>
|
||||||
|
SECRET_PAYLOAD_SECRET_VERSION: v1
|
||||||
|
SECRET_TOKEN_VERSION: v1
|
||||||
|
SECRET_MONGO_PASSWORD_VERSION: v1
|
||||||
|
NGINX_CONF_VERSION: v1
|
||||||
|
depends_on:
|
||||||
|
- publish astro container
|
||||||
|
- publish payload container
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
event:
|
||||||
|
exclude:
|
||||||
|
- pull_request
|
||||||
|
|
11
.env
Normal file
11
.env
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
NAME=astroad
|
||||||
|
ASTRO_HOST=localhost:3000
|
||||||
|
PAYLOAD_HOST=payload:3001
|
||||||
|
PAYLOAD_URL=http://localhost:3001
|
||||||
|
PAYLOAD_PORT=3001
|
||||||
|
PAYLOAD_SECRET=supersecretkey
|
||||||
|
MONGODB_URI=mongodb://payload:test@mongo:27017
|
||||||
|
MONGODB_USER=payload
|
||||||
|
MONGODB_PW=test
|
||||||
|
TOKEN=supersecrettoken
|
||||||
|
REPOSITORY=mooxl/astroad
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
data
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
20
LICENSE
Normal file
20
LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Max Schmidt
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
66
README.md
Normal file
66
README.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Astroad
|
||||||
|
|
||||||
|
Astroad is a pre-configured setup for Astro and Payloadcms, designed to make it easy for you to start building your website. With Astroad, you'll have a complete development environment that you can run locally using Docker. This setup simplifies the testing and development of your website before deploying it to a production environment.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before getting started with Astroad, make sure you have the necessary software installed:
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
- Node.js
|
||||||
|
- Yarn
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
While there's no configuration necessary for local development, deployment via Github Workflows requires specific secrets and variables to be set.
|
||||||
|
|
||||||
|
### Secrets:
|
||||||
|
|
||||||
|
- `USER`: User on the server
|
||||||
|
- `HOST`: IP or URL of the server
|
||||||
|
- `KEY`: SSH KEY for connecting to the server
|
||||||
|
- `MONGODB_PW`: Password for MongoDB
|
||||||
|
- `MONGODB_USER`: User for MongoDB
|
||||||
|
- `PATH`: Path where the repository resides on the server
|
||||||
|
- `PAYLOAD_PORT`: Port at which Payload listens
|
||||||
|
- `PAYLOAD_SECRET`: String to encrypt Payload data
|
||||||
|
- `TOKEN`: Github Access Token for the webhook to trigger the payload.yml workflow and execute a new Astro build
|
||||||
|
|
||||||
|
### Variables:
|
||||||
|
|
||||||
|
- `ASTRO_HOST`: Hostdomain of the Frontend
|
||||||
|
- `PAYLOAD_HOST`: Hostdomain of the CMS
|
||||||
|
- `PAYLOAD_URL`: URL of the CMS
|
||||||
|
- `NAME`: Name of the Container and Project
|
||||||
|
|
||||||
|
Please remember to set these secrets and variables in your repository settings to ensure a successful deployment through Github Workflows.
|
||||||
|
|
||||||
|
Once the secrets and variables are set on GitHub, they will replace the existing ones in the `.env` file on the server during deployment. This is done by the push.yml workflow, which replaces the placeholders in the `.env` with the actual secrets and variables defined in the repository settings. Please ensure that the names of your secrets and variables match with the placeholders in the `.env` file.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
To get started with Astroad, you'll need to have Docker and NPM || Yarn || PNPM installed on your machine.
|
||||||
|
|
||||||
|
You have two options for getting the repository:
|
||||||
|
|
||||||
|
1. Use the 'Use this template' button on the Github repository. This will create a new repository in your Github account with the same directory structure and files as Astroad. After the new repository is created, you can clone it to your local machine.
|
||||||
|
1. Alternatively, you can directly clone the Astroad repository: git clone https://github.com/mooxl/astroad.git. If you choose this option, remember to change the origin of your remote repository to a new one to avoid pushing changes directly to the Astroad repository. This can be done with the command: git remote set-url origin https://github.com/USERNAME/REPOSITORY.git where USERNAME is your username and REPOSITORY is the name of your new repository.
|
||||||
|
|
||||||
|
Once you've cloned the repository or created your own from the template, follow these steps:
|
||||||
|
|
||||||
|
1. Change into the repository directory: `cd {newName}`
|
||||||
|
1. Start the containers: `yarn dev`
|
||||||
|
|
||||||
|
This will start up the Astro, Payloadcms and Mongo containers and make them available on your local machine. Astro will be served at http://localhost:3000 and the Payload will be available at http://localhost:3001.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
The `docker-compose.yml` and `docker-compose-dev.yml` files includes everything you need to run the containers. The containers use the environment variables declared in the `.env` file and mounted volumes to store data persistently even after the containers are stopped and started.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
Deployment is handled by a Github Actions Workflow on every push. It logs into the server via SSH, pulls or clones the latest version of the repository, and runs `yarn prod`.
|
||||||
|
|
||||||
|
Because Astro is completely static, a content change in the CMS must trigger a new build of Astro. Therefore, there’s a `payload.yml` workflow that gets triggered by a webhook after every content change from Payload.
|
||||||
|
|
||||||
|
Ensure you have Traefik set up as a reverse proxy before deployment. The prod script will launch your site in a production-ready environment.
|
3
astro/.dockerignore
Normal file
3
astro/.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
Dockerfile
|
||||||
|
README.md
|
0
astro/.env
Normal file
0
astro/.env
Normal file
21
astro/.gitignore
vendored
Normal file
21
astro/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# build output
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# generated types
|
||||||
|
.astro/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
|
||||||
|
# macOS-specific files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# types
|
||||||
|
src/types.ts
|
11
astro/.prettierrc
Normal file
11
astro/.prettierrc
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-astro", "prettier-plugin-tailwindcss"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "*.astro",
|
||||||
|
"options": {
|
||||||
|
"parser": "astro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
astro/Dockerfile
Normal file
16
astro/Dockerfile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
FROM node:lts-alpine as base
|
||||||
|
WORKDIR /base
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
FROM base AS dev
|
||||||
|
ENV NODE_ENV=development
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["yarn","dev"]
|
||||||
|
|
||||||
|
FROM base AS build
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
WORKDIR /build
|
||||||
|
COPY --from=base /base .
|
||||||
|
ADD "https://random-uuid.deno.dev" skipcache
|
29
astro/astro.config.mjs
Normal file
29
astro/astro.config.mjs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { defineConfig } from "astro/config";
|
||||||
|
import tailwind from "@astrojs/tailwind";
|
||||||
|
import image from "@astrojs/image";
|
||||||
|
import sitemap from "@astrojs/sitemap";
|
||||||
|
import prefetch from "@astrojs/prefetch";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
compressHTML: true,
|
||||||
|
build: {
|
||||||
|
inlineStylesheets: "auto",
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
viewTransitions: true,
|
||||||
|
},
|
||||||
|
integrations: [
|
||||||
|
tailwind({
|
||||||
|
config: {
|
||||||
|
applyBaseStyles: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
image({
|
||||||
|
serviceEntryPoint: "@astrojs/image/sharp",
|
||||||
|
}),
|
||||||
|
prefetch({
|
||||||
|
selector: "a",
|
||||||
|
}),
|
||||||
|
sitemap(),
|
||||||
|
],
|
||||||
|
});
|
36
astro/nginx.conf
Normal file
36
astro/nginx.conf
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include mime.types;
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_buffers 16 8k;
|
||||||
|
gzip_http_version 1.1;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /error_page.html {
|
||||||
|
internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|htm|html)$ {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
expires 30d;
|
||||||
|
add_header Pragma public;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 404 /error_page.html;
|
||||||
|
}
|
||||||
|
}
|
27
astro/package.json
Normal file
27
astro/package.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "astroad",
|
||||||
|
"description": "Astroad - Astro",
|
||||||
|
"type": "module",
|
||||||
|
"version": "1.1",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev --host",
|
||||||
|
"build": "astro build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/image": "^0.17.3",
|
||||||
|
"@astrojs/prefetch": "^0.3.0",
|
||||||
|
"@astrojs/sitemap": "^2.0.2",
|
||||||
|
"@astrojs/tailwind": "4.0.0",
|
||||||
|
"astro": "^2.10.12",
|
||||||
|
"css-select": "5.1.0",
|
||||||
|
"sharp": "^0.32.6",
|
||||||
|
"slate-serializers": "0.4.1",
|
||||||
|
"tailwindcss": "^3.3.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^3.0.2",
|
||||||
|
"prettier-plugin-astro": "^0.11.1",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.5.4"
|
||||||
|
}
|
||||||
|
}
|
9
astro/public/favicon.svg
Normal file
9
astro/public/favicon.svg
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||||
|
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||||
|
<style>
|
||||||
|
path { fill: #000; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
path { fill: #FFF; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 749 B |
BIN
astro/public/fonts/Plex-Bold.woff2
Normal file
BIN
astro/public/fonts/Plex-Bold.woff2
Normal file
Binary file not shown.
BIN
astro/public/fonts/Plex-Regular.woff2
Normal file
BIN
astro/public/fonts/Plex-Regular.woff2
Normal file
Binary file not shown.
27
astro/src/components/Content.astro
Normal file
27
astro/src/components/Content.astro
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
import { Image } from "@astrojs/image/components";
|
||||||
|
import { getContentArray } from "@/utils/helpers";
|
||||||
|
import { getImageSrc } from "@/utils/payload";
|
||||||
|
const { content } = Astro.props;
|
||||||
|
const contentArray = getContentArray(content);
|
||||||
|
---
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
contentArray.map((value) => {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return <article set:html={value} />;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={getImageSrc(value.src)}
|
||||||
|
width={value.width}
|
||||||
|
height={value.height}
|
||||||
|
format="webp"
|
||||||
|
alt="hallo"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
1
astro/src/env.d.ts
vendored
Normal file
1
astro/src/env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="astro/client" />
|
36
astro/src/layouts/Layout.astro
Normal file
36
astro/src/layouts/Layout.astro
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<title>{title}</title>
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: "Plex";
|
||||||
|
src: url("/fonts/Plex-Regular.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Plex";
|
||||||
|
src: url("/fonts/Plex-Bold.woff2") format("woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="mx-auto max-w-7xl bg-gray px-6 py-8 font-plex text-gray-200">
|
||||||
|
<slot />
|
||||||
|
</body>
|
||||||
|
</html>
|
45
astro/src/pages/index.astro
Normal file
45
astro/src/pages/index.astro
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
import { getPosts } from "@/utils/payload";
|
||||||
|
|
||||||
|
const posts = await getPosts();
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="Astroad">
|
||||||
|
<main class="" >
|
||||||
|
<h1 class="font-bold text-5xl">Astroad</h1>
|
||||||
|
<p class="mt-3 text-lg">
|
||||||
|
Astroad is a pre-configured setup for Astro and Payloadcms that makes it
|
||||||
|
easy to get started with building your website. With Astroad, you'll have
|
||||||
|
a complete development environment that you can run locally using Docker.
|
||||||
|
This makes it easy to test and develop your website before deploying it to
|
||||||
|
a production environment.
|
||||||
|
<br />
|
||||||
|
When you're ready to deploy the website on your own server, Astrotus
|
||||||
|
comes with a production environment that requires the use of Traefik as a
|
||||||
|
reverse proxy. This setup provides a secure and scalable production
|
||||||
|
environment for your website.
|
||||||
|
</p>
|
||||||
|
<h2 class="mt-6 font-bold text-2xl">Posts</h2>
|
||||||
|
<div class="flex gap-4 mt-3 flex-wrap">
|
||||||
|
{
|
||||||
|
posts.length > 0 ? (
|
||||||
|
posts.map((post) => (
|
||||||
|
<a href={`/posts/${post.id}/`}>
|
||||||
|
<article class="text-gray bg-gray-light px-5 py-3 rounded-md shadow-md w-64 text-center hover:-translate-y-1 transition-transform">
|
||||||
|
<h3 class="font-bold text-lg" transition:name=`title-${post.id}`>{post.title}</h3>
|
||||||
|
{post.publishedDate && (
|
||||||
|
<p>
|
||||||
|
{new Date(post.publishedDate).toLocaleDateString("de-DE")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</article>
|
||||||
|
</a>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<p>Add Posts in Payloadcms</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
31
astro/src/pages/posts/[id].astro
Normal file
31
astro/src/pages/posts/[id].astro
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
import Content from "@/components/Content.astro";
|
||||||
|
import type { Post } from "@/types";
|
||||||
|
import { getPost, getPosts } from "@/utils/payload";
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const posts = await getPosts();
|
||||||
|
const paths = posts.map((post: Post) => ({
|
||||||
|
params: { id: post.id },
|
||||||
|
}));
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id } = Astro.params;
|
||||||
|
const post = id && (await getPost(id));
|
||||||
|
---
|
||||||
|
|
||||||
|
{
|
||||||
|
post ? (
|
||||||
|
<Layout title={`Astroad | ${post.title!}`}>
|
||||||
|
<div class="space-y-3 my-3">
|
||||||
|
<a href="/">BACK</a>
|
||||||
|
<h1 class="font-bold text-5xl" transition:name=`title-${post.id}`>{post.title}</h1>
|
||||||
|
{post.content && <Content content={post.content} />}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
) : (
|
||||||
|
<div>404</div>
|
||||||
|
)
|
||||||
|
}
|
41
astro/src/utils/helpers.ts
Normal file
41
astro/src/utils/helpers.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { payloadSlateToDomConfig, slateToHtml } from "slate-serializers";
|
||||||
|
import { Element } from "domhandler";
|
||||||
|
|
||||||
|
export const getContentArray = (content: any) => {
|
||||||
|
const html = slateToHtml(content, {
|
||||||
|
...payloadSlateToDomConfig,
|
||||||
|
elementTransforms: {
|
||||||
|
...payloadSlateToDomConfig.elementTransforms,
|
||||||
|
upload: ({ node }) =>
|
||||||
|
// @ts-ignore
|
||||||
|
new Element("img", {
|
||||||
|
src: node.value.filename,
|
||||||
|
width: `${node.value.width}`,
|
||||||
|
height: `${node.value.height}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}).replaceAll("<p></p>", "<p> </p>");
|
||||||
|
const htmlImageArray: (
|
||||||
|
| string
|
||||||
|
| { src: string; width: number; height: number }
|
||||||
|
)[] = [];
|
||||||
|
let lastIndex = 0;
|
||||||
|
while (true) {
|
||||||
|
const imgStartIndex = html.indexOf("<img", lastIndex);
|
||||||
|
if (imgStartIndex === -1) {
|
||||||
|
htmlImageArray.push(html.substring(lastIndex));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const imgEndIndex = html.indexOf(">", imgStartIndex) + 1;
|
||||||
|
const imgTag = html.substring(imgStartIndex, imgEndIndex);
|
||||||
|
const remainingHtml = html.substring(lastIndex, imgStartIndex);
|
||||||
|
const imgObject = {
|
||||||
|
src: imgTag.match(/src="(.*?)"/)![1],
|
||||||
|
width: +imgTag.match(/width="(.*?)"/)![1],
|
||||||
|
height: +imgTag.match(/height="(.*?)"/)![1],
|
||||||
|
};
|
||||||
|
htmlImageArray.push(remainingHtml, imgObject);
|
||||||
|
lastIndex = imgEndIndex;
|
||||||
|
}
|
||||||
|
return htmlImageArray;
|
||||||
|
};
|
13
astro/src/utils/payload.ts
Normal file
13
astro/src/utils/payload.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type { Post } from "@/types";
|
||||||
|
|
||||||
|
const url = import.meta.env.DEV
|
||||||
|
? "http://payload:3001"
|
||||||
|
: `${import.meta.env.PAYLOAD_URL}`;
|
||||||
|
|
||||||
|
export const getPosts = async () =>
|
||||||
|
(await (await fetch(`${url}/api/posts`)).json()).docs as Post[];
|
||||||
|
|
||||||
|
export const getPost = async (id: string) =>
|
||||||
|
(await (await fetch(`${url}/api/posts/${id}`)).json()) as Post;
|
||||||
|
|
||||||
|
export const getImageSrc = (src: string) => `${url}/media/${src}`;
|
20
astro/tailwind.config.cjs
Normal file
20
astro/tailwind.config.cjs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
||||||
|
theme: {
|
||||||
|
fontFamily: {
|
||||||
|
plex: ["Plex", "sans-serif"],
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
gray: {
|
||||||
|
DEFAULT: "#111111",
|
||||||
|
light: "#888888",
|
||||||
|
dark: "#222222",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
safelist: [],
|
||||||
|
plugins: [],
|
||||||
|
};
|
10
astro/tsconfig.json
Normal file
10
astro/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "astro/tsconfigs/strict",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["@astrojs/image/client"],
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4514
astro/yarn.lock
Normal file
4514
astro/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
95
compose.yml
Normal file
95
compose.yml
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
---
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: nginx:1.26.0
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
volumes:
|
||||||
|
- html_content:/usr/share/nginx/html
|
||||||
|
configs:
|
||||||
|
- source: nginx_default_conf
|
||||||
|
target: /etc/nginx/conf.d/default.conf
|
||||||
|
deploy:
|
||||||
|
update_config:
|
||||||
|
failure_action: rollback
|
||||||
|
order: start-first
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.services.${STACK_NAME}-astro.loadbalancer.server.port=80"
|
||||||
|
- "traefik.http.routers.${STACK_NAME}-astro.rule=Host(`${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${STACK_NAME}-astro.entrypoints=web-secure"
|
||||||
|
- "traefik.http.routers.${STACK_NAME}-astro.tls.certresolver=production"
|
||||||
|
|
||||||
|
payload:
|
||||||
|
image: git.autonomic.zone/autonomic-cooperative/justice-equity-technology-payload:latest
|
||||||
|
environment:
|
||||||
|
- "NAME=${STACK_NAME}"
|
||||||
|
- "PAYLOAD_URL=${STACK_NAME}_payload"
|
||||||
|
- "PAYLOAD_PORT=3001"
|
||||||
|
- "PAYLOAD_SECRET_FILE=/run/secrets/payload_secret"
|
||||||
|
- "MONGODB_USER=mongo"
|
||||||
|
- "MONGODB_HOST=${STACK_NAME}_mongo"
|
||||||
|
- "MONGODB_PORT=27017"
|
||||||
|
- "MONGODB_PASSWORD_FILE=/run/secrets/mongo_password"
|
||||||
|
- "TOKEN_FILE=/run/secrets/token"
|
||||||
|
secrets:
|
||||||
|
- mongo_password
|
||||||
|
- payload_secret
|
||||||
|
- token
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
- internal
|
||||||
|
deploy:
|
||||||
|
update_config:
|
||||||
|
failure_action: rollback
|
||||||
|
order: start-first
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.services.${STACK_NAME}-payload.loadbalancer.server.port=3001"
|
||||||
|
# FIXME switch to /admin probably using PathPrefix
|
||||||
|
- "traefik.http.routers.${STACK_NAME}-payload.rule=Host(`admin.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${STACK_NAME}-payload.entrypoints=web-secure"
|
||||||
|
- "traefik.http.routers.${STACK_NAME}-payload.tls.certresolver=production"
|
||||||
|
|
||||||
|
mongo:
|
||||||
|
image: mongo:6.0.5
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- mongo:/data/db
|
||||||
|
command:
|
||||||
|
- --storageEngine=wiredTiger
|
||||||
|
environment:
|
||||||
|
- "MONGO_INITDB_ROOT_USERNAME=mongo"
|
||||||
|
- "MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_password"
|
||||||
|
secrets:
|
||||||
|
- mongo_password
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
|
||||||
|
networks:
|
||||||
|
proxy:
|
||||||
|
external: true
|
||||||
|
internal:
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
payload_secret:
|
||||||
|
external: true
|
||||||
|
name: ${STACK_NAME}_payload_secret_${SECRET_PAYLOAD_SECRET_VERSION}
|
||||||
|
token:
|
||||||
|
external: true
|
||||||
|
name: ${STACK_NAME}_token_${SECRET_TOKEN_VERSION}
|
||||||
|
mongo_password:
|
||||||
|
external: true
|
||||||
|
name: ${STACK_NAME}_mongo_password_${SECRET_MONGO_PASSWORD_VERSION}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mongo:
|
||||||
|
html_content:
|
||||||
|
|
||||||
|
configs:
|
||||||
|
nginx_conf:
|
||||||
|
name: ${STACK_NAME}_nginx_conf_${NGINX_CONF_VERSION}
|
||||||
|
file: astro/nginx.conf
|
||||||
|
template_driver: golang
|
59
docker-compose.yml
Normal file
59
docker-compose.yml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
services:
|
||||||
|
astro:
|
||||||
|
container_name: ${NAME}-astro
|
||||||
|
restart: unless-stopped
|
||||||
|
build:
|
||||||
|
context: astro
|
||||||
|
target: de
|
||||||
|
networks:
|
||||||
|
- front
|
||||||
|
volumes:
|
||||||
|
- ./astro:/base
|
||||||
|
- /base/node_modules/
|
||||||
|
ports:
|
||||||
|
- 3000:3000
|
||||||
|
depends_on:
|
||||||
|
- payload
|
||||||
|
|
||||||
|
payload:
|
||||||
|
container_name: ${NAME}-payload
|
||||||
|
restart: unless-stopped
|
||||||
|
build:
|
||||||
|
context: payload
|
||||||
|
environment:
|
||||||
|
NAME: ${NAME}
|
||||||
|
PAYLOAD_URL: ${PAYLOAD_URL}
|
||||||
|
PAYLOAD_PORT: ${PAYLOAD_PORT}
|
||||||
|
PAYLOAD_SECRET: ${PAYLOAD_SECRET}
|
||||||
|
MONGODB_URI: ${MONGODB_URI}
|
||||||
|
TOKEN: ${TOKEN}
|
||||||
|
volumes:
|
||||||
|
- ./payload/src:/base/src
|
||||||
|
- ./astro/src/types.ts:/types.ts
|
||||||
|
ports:
|
||||||
|
- 3001:3001
|
||||||
|
networks:
|
||||||
|
- front
|
||||||
|
- back
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
|
||||||
|
mongo:
|
||||||
|
container_name: ${NAME}-mongo
|
||||||
|
image: mongo:6.0.5
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./data/mongo:/data/db
|
||||||
|
command:
|
||||||
|
- --storageEngine=wiredTiger
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGODB_USER}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PW}
|
||||||
|
networks:
|
||||||
|
- back
|
||||||
|
ports:
|
||||||
|
- 27017:27017
|
||||||
|
|
||||||
|
networks:
|
||||||
|
front:
|
||||||
|
back:
|
11
package.json
Normal file
11
package.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "astroad",
|
||||||
|
"description": "A pre-configured setup for easy website development with Astro and Payload CMS using Docker.",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "1.1",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "docker compose -f docker-compose.yml -f docker-compose-dev.yml up --build",
|
||||||
|
"prod": "docker compose -f docker-compose.yml -f docker-compose-prod.yml up -d --build",
|
||||||
|
"stop": "docker compose -f docker-compose.yml -f docker-compose-dev.yml down && docker compose -f docker-compose.yml -f docker-compose-prod.yml down"
|
||||||
|
}
|
||||||
|
}
|
2
payload/.dockerignore
Normal file
2
payload/.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
Dockerfile
|
5
payload/.gitignore
vendored
Normal file
5
payload/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
src/media
|
31
payload/Dockerfile
Normal file
31
payload/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
FROM node:lts as base
|
||||||
|
WORKDIR /base
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
FROM base AS dev
|
||||||
|
ENV NODE_ENV=development
|
||||||
|
EXPOSE 3001
|
||||||
|
CMD ["yarn","dev"]
|
||||||
|
|
||||||
|
|
||||||
|
FROM base AS build
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
WORKDIR /build
|
||||||
|
COPY --from=base /base .
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
FROM build as prod
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
WORKDIR /prod
|
||||||
|
COPY package*.json .
|
||||||
|
RUN yarn install --production
|
||||||
|
|
||||||
|
COPY --from=build /build/tsconfig.json ./tsconfig.json
|
||||||
|
COPY --from=build /build/dist ./dist
|
||||||
|
COPY --from=build /build/build ./build
|
||||||
|
EXPOSE 3000
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
CMD ["yarn", "serve"]
|
32
payload/docker-entrypoint.sh
Executable file
32
payload/docker-entrypoint.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
file_env() {
|
||||||
|
local var="$1"
|
||||||
|
local fileVar="${var}_FILE"
|
||||||
|
local def="${2:-}"
|
||||||
|
|
||||||
|
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
||||||
|
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local val="$def"
|
||||||
|
if [ "${!var:-}" ]; then
|
||||||
|
val="${!var}"
|
||||||
|
elif [ "${!fileVar:-}" ]; then
|
||||||
|
val="$(< "${!fileVar}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export "$var"="$val"
|
||||||
|
unset "$fileVar"
|
||||||
|
}
|
||||||
|
|
||||||
|
file_env "TOKEN"
|
||||||
|
file_env "MONGODB_PASSWORD"
|
||||||
|
file_env "PAYLOAD_SECRET"
|
||||||
|
|
||||||
|
export MONGODB_URI="mongodb://$MONGODB_USER:$MONGODB_PASSWORD@$MONGODB_HOST:$MONGODB_PORT"
|
||||||
|
|
||||||
|
"$@"
|
5
payload/nodemon.json
Normal file
5
payload/nodemon.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ext": "ts",
|
||||||
|
"ignore": ["src/types.ts"],
|
||||||
|
"exec": "yarn generate:types && ts-node src/server.ts"
|
||||||
|
}
|
28
payload/package.json
Normal file
28
payload/package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "astroad",
|
||||||
|
"description": "Astroad - Payload",
|
||||||
|
"version": "1.1",
|
||||||
|
"main": "dist/server.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
|
||||||
|
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts node -r tsconfig-paths/register node_modules/payload/dist/bin/index.js build",
|
||||||
|
"build:server": "tsc",
|
||||||
|
"build": "yarn build:payload && yarn build:server",
|
||||||
|
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js node -r tsconfig-paths/register dist/server.js",
|
||||||
|
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts node -r tsconfig-paths/register node_modules/payload/dist/bin/index.js generate:types"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"payload": "^1.15.6",
|
||||||
|
"tsconfig-paths": "^4.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.18",
|
||||||
|
"nodemon": "^3.0.1",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
}
|
||||||
|
}
|
25
payload/src/collections/Media.ts
Normal file
25
payload/src/collections/Media.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
|
||||||
|
export const Media: CollectionConfig = {
|
||||||
|
slug: "media",
|
||||||
|
admin: {},
|
||||||
|
access: {
|
||||||
|
read: (): boolean => true,
|
||||||
|
create: () => true,
|
||||||
|
update: () => true,
|
||||||
|
},
|
||||||
|
upload: {
|
||||||
|
staticURL: "/media",
|
||||||
|
staticDir: "media",
|
||||||
|
mimeTypes: ["image/*"],
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "alt",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Media;
|
98
payload/src/collections/Posts.ts
Normal file
98
payload/src/collections/Posts.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
const Posts: CollectionConfig = {
|
||||||
|
slug: "posts",
|
||||||
|
admin: {
|
||||||
|
defaultColumns: ["title", "author", "status"],
|
||||||
|
useAsTitle: "title",
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
read: () => true,
|
||||||
|
create: () => true,
|
||||||
|
update: () => true,
|
||||||
|
},
|
||||||
|
hooks: {
|
||||||
|
afterChange: [
|
||||||
|
async () => {
|
||||||
|
console.log(process.env.TOKEN);
|
||||||
|
|
||||||
|
try {
|
||||||
|
process.env.NODE_ENV !== "development" &&
|
||||||
|
console.log(
|
||||||
|
await fetch(
|
||||||
|
`https://api.github.com/repos/${process.env.REPOSITORY}/dispatches`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/vnd.github.everest-preview+json",
|
||||||
|
Authorization: `token ${process.env.TOKEN}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
event_type: "payload_update",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "title",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hallo",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "publishedDate",
|
||||||
|
type: "date",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "content",
|
||||||
|
type: "richText",
|
||||||
|
admin: {
|
||||||
|
elements: ["h2", "h3", "h4", "link", "ol", "ul", "upload"],
|
||||||
|
leaves: ["bold", "italic", "underline"],
|
||||||
|
upload: {
|
||||||
|
collections: {
|
||||||
|
media: {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "imagel",
|
||||||
|
type: "upload",
|
||||||
|
relationTo: "media",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "status",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: "draft",
|
||||||
|
label: "Draft",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "published",
|
||||||
|
label: "Published",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: "draft",
|
||||||
|
admin: {
|
||||||
|
position: "sidebar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Posts;
|
21
payload/src/collections/Users.ts
Normal file
21
payload/src/collections/Users.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { CollectionConfig } from 'payload/types';
|
||||||
|
|
||||||
|
const Users: CollectionConfig = {
|
||||||
|
slug: 'users',
|
||||||
|
auth: true,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'email',
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
read: () => true,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
// Email added by default
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Users;
|
26
payload/src/payload.config.ts
Normal file
26
payload/src/payload.config.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { buildConfig } from "payload/config";
|
||||||
|
import path from "path";
|
||||||
|
import Posts from "@/collections/Posts";
|
||||||
|
import Users from "@/collections/Users";
|
||||||
|
import Media from "@/collections/Media";
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
serverURL: process.env.PAYLOAD_URL,
|
||||||
|
admin: {
|
||||||
|
user: Users.slug,
|
||||||
|
webpack: (config) => ({
|
||||||
|
...config,
|
||||||
|
resolve: {
|
||||||
|
...config.resolve,
|
||||||
|
alias: {
|
||||||
|
...config.resolve.alias,
|
||||||
|
"@": path.resolve(__dirname, "./"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
collections: [Posts, Users, Media],
|
||||||
|
typescript: {
|
||||||
|
outputFile: path.resolve("/", "types.ts"),
|
||||||
|
},
|
||||||
|
});
|
21
payload/src/server.ts
Normal file
21
payload/src/server.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import express from "express";
|
||||||
|
import payload from "payload";
|
||||||
|
|
||||||
|
require("dotenv").config();
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.get("/", (_, res) => {
|
||||||
|
res.redirect("/admin");
|
||||||
|
});
|
||||||
|
|
||||||
|
payload.init({
|
||||||
|
secret: process.env.PAYLOAD_SECRET,
|
||||||
|
mongoURL: process.env.MONGODB_URI,
|
||||||
|
express: app,
|
||||||
|
onInit: () => {
|
||||||
|
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use("/media", express.static("media"));
|
||||||
|
app.listen(process.env.PAYLOAD_PORT);
|
18
payload/tsconfig.json
Normal file
18
payload/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"strict": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*", "./dist/*", "./dist/src/*"]
|
||||||
|
},
|
||||||
|
"jsx": "react"
|
||||||
|
},
|
||||||
|
"ts-node": {
|
||||||
|
"transpileOnly": true,
|
||||||
|
"require": ["tsconfig-paths/register"]
|
||||||
|
}
|
||||||
|
}
|
6974
payload/yarn.lock
Normal file
6974
payload/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"include": ["*.ts"],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./astro/tsconfig.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./payload/tsconfig.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user