Compare commits
13 Commits
92e3de7340
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ea12adf484 | |||
| ef8d90651e | |||
| 1dd1ff893e | |||
| d073e021f3 | |||
| c78bd0188b | |||
| cff329a4c4 | |||
| f40e8c638c | |||
| 575fa686ff | |||
| 5ecfc5bb45 | |||
| 8c46bde9ce | |||
| aa163c6c6e | |||
| 68425fe793 | |||
| 21387170f1 |
@@ -71,6 +71,7 @@ docs/
|
||||
# CI/CD configuration files
|
||||
.github/
|
||||
.gitlab-ci.yml
|
||||
.gitea/
|
||||
.travis.yml
|
||||
.circleci/
|
||||
Jenkinsfile
|
||||
|
||||
55
.gitea/workflows/deploy.yml
Normal file
55
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
name: Build and Deploy NextJS SculptedArc Website
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
# 1. Log into your self-hosted gitea container storage layer
|
||||
- name: Log in to gitea Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: gitea.sculpted-arc.co.uk # Change to your gitea domain
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.TOKEN_GITEA }} # Store a personal access token in your repo secrets for security
|
||||
|
||||
# 2. Build the Dockerfile and upload the compiled app image
|
||||
- name: Build and Push Docker Image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: gitea.sculpted-arc.co.uk/james-admin/sculptedarcwebsite:latest
|
||||
|
||||
# 3. Securely SSH to the host using masked secrets
|
||||
- name: Deploy to Server via SSH
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
port: ${{ secrets.SSH_PORT }}
|
||||
username: james
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }} # Completely invisible to anyone viewing code
|
||||
passphrase: ${{ secrets.SSH_PASSPHRASE }}
|
||||
script: |
|
||||
cd /home/james/docker/sculpted-arc-site
|
||||
|
||||
# Authenticate the host machine to pull from gitea's registry
|
||||
docker login -u ${{ gitea.actor }} -p ${{ secrets.TOKEN_GITEA }} gitea.sculpted-arc.co.uk
|
||||
|
||||
# Pull down the fresh image we just built and restart gracefully
|
||||
docker compose pull
|
||||
docker compose up -d --remove-orphans
|
||||
37
README.md
37
README.md
@@ -1,36 +1 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
This is the source code for my sculpted arc website. More documentation will be written soon
|
||||
32
app/case-studies/[slug]/page.tsx
Normal file
32
app/case-studies/[slug]/page.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
// src/app/blog/[slug]/page.tsx
|
||||
import { getPostBySlug } from '@/lib/case-study';
|
||||
import { notFound } from 'next/navigation';
|
||||
import parse from 'html-react-parser';
|
||||
|
||||
|
||||
interface StudyPageProps {
|
||||
params: Promise<{ slug: string }>;
|
||||
}
|
||||
|
||||
export default async function BlogPostPage({ params }: StudyPageProps) {
|
||||
// In Next.js 15+, params is a Promise and must be awaited
|
||||
const { slug } = await params;
|
||||
const caseStudy = await getPostBySlug(slug);
|
||||
|
||||
if (!caseStudy) {
|
||||
notFound(); // Triggers the closest 404 page if the file doesn't exist
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="max-w-2xl mx-auto py-10 px-4">
|
||||
<header className="mb-8">
|
||||
<h1 className="text-4xl font-bold mb-2">{caseStudy.title}</h1>
|
||||
</header>
|
||||
|
||||
{/* Render the parsed HTML safely */}
|
||||
<div className="prose dark:prose-invert">
|
||||
{parse(caseStudy.contentHtml)}
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
@@ -16,8 +16,8 @@ const geistMono = Geist_Mono({
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
title: "Sculpted Arc",
|
||||
description: "Web and software solutions for companies and people around the world",
|
||||
};
|
||||
|
||||
export const viewport = {
|
||||
@@ -39,7 +39,7 @@ export default function RootLayout({
|
||||
<link rel="icon" href={favicon.src} />
|
||||
</head>
|
||||
|
||||
<body className="min-h-full flex flex-col dark:bg-black">
|
||||
<body className="min-h-full flex flex-col dark:bg-black dark">
|
||||
<SiteHeader />
|
||||
<div className="flex min-h-screen flex-col bg-zinc-50 font-sans dark:bg-black">
|
||||
<main className="mx-auto flex w-full max-w-7xl flex-1 flex-col items-center justify-between bg-white px-8 py-32 dark:bg-black sm:items-start">
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function Home() {
|
||||
]
|
||||
|
||||
const picWithText = {
|
||||
title: "Building a better web, one pixel at a time",
|
||||
title: "Hand crafted software, built for scale",
|
||||
text: "Over the last year, we've had the privilege of working with a diverse range of clients, from local artisans to growing enterprises. Each project has been an opportunity to learn, innovate, and create something truly unique. Our commitment to quality and customer satisfaction has earned us a reputation for excellence in the web development industry.",
|
||||
src: logo.src,
|
||||
reverse: false
|
||||
|
||||
@@ -11,7 +11,6 @@ export default function HeroSection({description, buttonText, imageSrc }: {descr
|
||||
</div>
|
||||
<div className="w-full md:w-1/2">
|
||||
<h1 className="mb-4 font-bold text-heading text-6xl sm:text-7xl"><span className="text-transparent bg-clip-text bg-gradient-to-r bg-violet-800 from-sky-400">Sculpted Arc</span><br/> Web Solutions</h1>
|
||||
|
||||
<hr className="w-1/4 mb-7 mt-8 border-gray-700 border-2 rounded-2xl"/>
|
||||
|
||||
<p className="text-lg font-normal text-body lg:text-xl">{description}</p>
|
||||
|
||||
5
content/case-studies/study-one.md
Normal file
5
content/case-studies/study-one.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Case Study One"
|
||||
---
|
||||
|
||||
This is the fist case study
|
||||
1
content/case-studies/study-two.md
Normal file
1
content/case-studies/study-two.md
Normal file
@@ -0,0 +1 @@
|
||||
Hello, this is case study two
|
||||
19
deploy.yml.bak
Normal file
19
deploy.yml.bak
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Build and Deploy NextJS SculptedArc Website
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
|
||||
steps:
|
||||
# 1. Log into your self-hosted gitea container storage layer
|
||||
- name: Log in to gitea Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: gitea.sculpted-arc.co.uk # Change to your gitea domain
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.TOKEN_GITEA }} # Store a personal access token in your repo secrets for security
|
||||
33
lib/case-study.ts
Normal file
33
lib/case-study.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// src/lib/blog.ts
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import matter from 'gray-matter';
|
||||
import { remark } from 'remark';
|
||||
import html from 'remark-html';
|
||||
|
||||
const postsDirectory = path.join(process.cwd(), 'content/case-studies');
|
||||
|
||||
export async function getPostBySlug(slug: string) {
|
||||
const fullPath = path.join(postsDirectory, `${slug}.md`);
|
||||
|
||||
// Guard against file system traversal attacks or missing files
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileContents = fs.readFileSync(fullPath, 'utf8');
|
||||
|
||||
// Use gray-matter to parse the study metadata section
|
||||
const { data, content } = matter(fileContents);
|
||||
|
||||
// Use remark to convert markdown into HTML string
|
||||
const processedContent = await remark().use(html).process(content);
|
||||
const contentHtml = processedContent.toString();
|
||||
|
||||
return {
|
||||
slug,
|
||||
contentHtml,
|
||||
title: data.title || 'Untitled Study',
|
||||
...data,
|
||||
};
|
||||
}
|
||||
@@ -9,10 +9,14 @@
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"gray-matter": "^4.0.3",
|
||||
"html-react-parser": "^6.1.3",
|
||||
"lucide-react": "^1.17.0",
|
||||
"next": "16.2.6",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
"react-dom": "19.2.4",
|
||||
"remark": "^15.0.1",
|
||||
"remark-html": "^16.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
|
||||
769
pnpm-lock.yaml
generated
769
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
allowBuilds:
|
||||
sharp@0.34.5: true
|
||||
unrs-resolver@1.11.1: true
|
||||
unrs-resolver@1.11.1: true
|
||||
|
||||
onlyBuiltDependencies:
|
||||
- sharp
|
||||
- unrs-resolver
|
||||
|
||||
Reference in New Issue
Block a user