Compare commits

...

No commits in common. "9d81ce456b1f5ee508310e5ae3f12257c5af58e5" and "8c61d6647cf5eb0b1611a1aa495f42bfe18af7b2" have entirely different histories.

33 changed files with 299 additions and 6684 deletions

8
.gitattributes vendored Normal file
View File

@ -0,0 +1,8 @@
# Auto detect text files and perform LF normalization
* text eol=LF
*.ts text
*.spec.ts text
# Ignore binary files >:(
*.png binary
*.jpg binary

View File

@ -0,0 +1,69 @@
name: 🐛 Bug Report
description: Something isn't working as expected? Let us know!
title: '[BUG] - '
labels:
- "status/awaiting triage"
body:
- type: checkboxes
id: attestations
attributes:
label: Attestations
description: "By checking the boxes below, I certify that:"
options:
- label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)"
validations:
required: true
- label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
validations:
required: true
- label: I have confirmed that the issue I am opening is unique, and has not already been reported (whether closed or not).
validations:
required: true
- label: I have reviewed the [Security Policy](https://docs.nhcarrigan.com/legal/security/) and have determined that this is not a security vulnerability.
validations:
required: true
- type: textarea
id: description
attributes:
label: "Describe your Issue:"
description: A clear and concise description of what the bug is.
validations:
required: true
- type: dropdown
id: reproduce
attributes:
label: Can you reproduce this issue?
options:
- Yes
- No
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: "Steps to Reproduce:"
description: Steps to reproduce the behavior.
- type: input
id: os
attributes:
label: "Operating System:"
description: The operating system you are using, including the version/build number.
validations:
required: true
# Remove this section for non-web apps.
- type: input
id: browser
attributes:
label: "Browser:"
description: The browser you are using, including the version number.
validations:
required: true
- type: dropdown
attributes:
label: Are you willing and able to contribute a fix?
options:
- Yes
- No
validations:
required: true

View File

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: "Discord"
url: "https://chat.nhcarrigan.com"
about: "Chat with us directly."

View File

@ -0,0 +1,46 @@
name: 💭 Feature Proposal
description: Have an idea for how we can improve? Share it here!
title: '[FEAT] - '
labels:
- "status/awaiting triage"
body:
- type: checkboxes
id: attestations
attributes:
label: Attestations
description: "By checking the boxes below, I certify that:"
options:
- label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)"
validations:
required: true
- label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
validations:
required: true
- label: I have confirmed that the issue I am opening is unique, and has not already been reported (whether closed or not).
validations:
required: true
- label: I have reviewed the [Security Policy](https://docs.nhcarrigan.com/legal/security/) and have determined that this is not a security vulnerability.
validations:
required: true
- type: textarea
id: description
attributes:
label: "Describe your Idea:"
description: A clear and concise description of the feature you would like added.
validations:
required: true
- type: textarea
id: solution
attributes:
label: "What problem does this feature solve?"
description: Why are you requesting this feature? How would it improve your experience with the product?
validations:
required: true
- type: dropdown
attributes:
label: Are you willing and able to contribute this feature?
options:
- Yes
- No
validations:
required: true

View File

@ -0,0 +1,34 @@
name: ❓ Other Issue
description: I have something that is neither a bug nor a feature request.
title: '[OTHER] - '
labels:
- "status/awaiting triage"
body:
- type: checkboxes
id: attestations
attributes:
label: Attestations
description: "By checking the boxes below, I certify that:"
options:
- label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)"
validations:
required: true
- label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
validations:
required: true
- label: I have confirmed that the issue I am opening is unique, and has not already been reported (whether closed or not).
validations:
required: true
- label: I have reviewed the [Security Policy](https://docs.nhcarrigan.com/legal/security/) and have determined that this is not a security vulnerability.
validations:
required: true
- label: This is not a feature request or bug report that I am mis-filing to avoid the issue template.
validations:
required: true
- type: textarea
id: description
attributes:
label: "Share your thoughts:"
description: Why are you opening this issue?
validations:
required: true

View File

@ -0,0 +1,91 @@
name: "Pull Request Template"
about: "Template for pulls"
body:
- type: textarea
id: explain
attributes:
label: "Explanation"
description: "Briefly explain WHY this pull request is necessary. Do not explain what it does, as that's evidenced in the changes."
validations:
required: true
- type: input
id: issue
attributes:
label: "Issue"
description: "My pull request relates to or resolves the following issue number:"
validations:
required: true
is_number: true
- type: checkboxes
id: attestations
attributes:
label: Attestations
description: "By checking the boxes below, I certify that:"
options:
- label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)"
validations:
required: true
- label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
validations:
required: true
- label: My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/).
validations:
required: true
- type: checkboxes
id: dependencies
attributes:
label: Dependencies
description: "My pull request adds or updates dependencies, so:"
options:
- label: I have pinned the dependencies to a specific patch version.
validations:
required: false
- type: checkboxes
id: style
attributes:
label: Style
description: "My contribution adheres to the following style guidelines:"
options:
- label: I have run the linter and resolved any errors.
validations:
required: true
- label: My pull request uses an appropriate title, matching the conventional commit standards.
validations:
required: true
- label: My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request.
validations:
required: true
- type: checkboxes
id: tests
attributes:
label: Tests
description: "My contribution includes the following tests:"
options:
- label: My contribution adds new code, and I have added tests to cover it.
validations:
required: false
- label: My contribution modifies existing code, and I have updated the tests to reflect these changes.
validations:
required: false
- label: All new and existing tests pass locally with my changes.
validations:
required: true
- label: Code coverage remains at or above the configured threshold.
validations:
required: true
- type: input
id: docs
attributes:
label: Documentation
description: "I have made the following PR to update the documentation site with my changes:"
validations:
required: true
- type: dropdown
id: version
attributes:
label: Versioning
description: "I believe my changes should be included in the following release:"
options:
- "Major - My pull request introduces a breaking change."
- "Minor - My pull request introduces a new non-breaking feature."
- "Patch - My pull request introduces bug fixes ONLY."

41
.gitignore vendored
View File

@ -1,41 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

3
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,3 @@
# Code of Conduct
Our Code of Conduct can be found here: https://docs.nhcarrigan.com/#/coc

3
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,3 @@
# Contributing
Our contributing guidelines can be found here: https://docs.nhcarrigan.com/#/contributing

5
LICENSE.md Normal file
View File

@ -0,0 +1,5 @@
# License
This software is licensed under our [global software license](https://docs.nhcarrigan.com/#/license).
Copyright held by Naomi Carrigan.

3
PRIVACY.md Normal file
View File

@ -0,0 +1,3 @@
# Privacy Policy
Our privacy policy can be found here: https://docs.nhcarrigan.com/#/privacy

View File

@ -1,36 +1,39 @@
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).
# New Repository Template
## Getting Started
This template contains all of our basic files for a new GitHub repository. There is also a handy workflow that will create an issue on a new repository made from this template, with a checklist for the steps we usually take in setting up a new repository.
First, run the development server:
If you're starting a Node.JS project with TypeScript, we have a [specific template](https://github.com/naomi-lgbt/nodejs-typescript-template) for that purpose.
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
## Readme
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Delete all of the above text (including this line), and uncomment the below text to use our standard readme template.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
<!-- # Project Name
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.
Project Description
## Learn More
## Live Version
To learn more about Next.js, take a look at the following resources:
This page is currently deployed. [View the live website.]
- [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.
## Feedback and Bugs
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
If you have feedback or a bug report, please feel free to open a GitHub issue!
## Deploy on Vercel
## Contributing
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.
If you would like to contribute to the project, you may create a Pull Request containing your proposed changes and we will review it as soon as we are able! Please review our [contributing guidelines](CONTRIBUTING.md) first.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
## Code of Conduct
Before interacting with our community, please read our [Code of Conduct](CODE_OF_CONDUCT.md).
## License
This software is licensed under our [global software license](https://docs.nhcarrigan.com/#/license).
Copyright held by Naomi Carrigan.
## Contact
We may be contacted through our [Chat Server](http://chat.nhcarrigan.com) or via email at `contact@nhcarrigan.com`. -->

3
SECURITY.md Normal file
View File

@ -0,0 +1,3 @@
# Security Policy
Our security policy can be found here: https://docs.nhcarrigan.com/#/security

3
TERMS.md Normal file
View File

@ -0,0 +1,3 @@
# Terms of Service
Our Terms of Service can be found here: https://docs.nhcarrigan.com/#/terms

View File

@ -1,17 +0,0 @@
import NaomisConfig from "@nhcarrigan/eslint-config";
export default [
...NaomisConfig,
{
rules: {
"@typescript-eslint/naming-convention": "off",
"unicorn/filename-case": "off",
"max-lines": "off",
"max-lines-per-function": "off",
complexity: "off",
"import/no-default-export": "off",
"import/extensions": ["warn", "never"],
"stylistic/max-len": "off",
},
},
];

View File

@ -1,16 +0,0 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
images: {
remotePatterns: [
{
hostname: "cdn.nhcarrigan.com",
},
],
},
};
export default nextConfig;

View File

@ -1,31 +0,0 @@
{
"name": "announcements",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint src --max-warnings 0"
},
"dependencies": {
"gray-matter": "4.0.3",
"next": "15.1.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-markdown": "9.0.3",
"remark-gfm": "4.0.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@nhcarrigan/eslint-config": "5.1.0",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.1.6",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
}

6256
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

View File

@ -1,23 +0,0 @@
---
title: "Migrating Our Community to Self-Hosted Platforms"
date: "2025-01-22"
summary: "Why we chose to move away from anything and everything that we can't control ourselves."
---
Hey friends,
We've been watching events unfold in our political climate, including tech leaders supporting a president that aims to oppress members of our LGBT+ community. As such, we've made the decision to migrate away from public community platforms and start self-hosting our own instead.
## What does this mean?
Well, there's a few things:
- First and foremost, the bulk of our communication is being moved to our [forum](https://chat.nhcarrigan.com). If you need to get in touch with us for *anything*, this is probably the best place to start. Additionally, conversations here are searchable and indexed by many crawlers.
- Our chat is migrating over to [IRC](https://irc.nhcarrigan.com). To protect the privacy of our community members, we do *not* run a bouncer. Which means anything you send can only be seen by users who are *currently online*. This ephemeral nature makes it nice for informal chatter, but leaves the forum as the best place for long-term conversation.
- For personal updates, we maintain our own [blog](https://blog.nhcarrigan.com). We also have a self-hosted [Sharkey instance](https://fedi.nhcarrigan.com) for smaller posts. Sign-ups are restricted to our family and polycule, but you can connect with us via any Mastodon-compliant instance!
## What if I don't want to join any of those?
That's fine! We'll still maintain a minimal presence on platforms like Discord and Bluesky. But our core focus for building our community is going to be on our self-hosted solutions, where we know our marginalised members are safe and can be protected.
We do hope to see you in our new home on the forum! 💜

View File

@ -1 +0,0 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 391 B

View File

@ -1 +0,0 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 128 B

View File

@ -1 +0,0 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

Before

Width:  |  Height:  |  Size: 385 B

View File

@ -1,34 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
font-family: "OpenDyslexic", monospace;
}
h1 {
@apply text-4xl;
}
h2 {
@apply text-2xl;
}
a {
@apply underline;
}
li {
@apply list-disc;
@apply list-inside;
@apply text-left;
}
p {
@apply text-justify;
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}

View File

@ -1,64 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Inter } from "next/font/google";
import Script from "next/script";
import type { Metadata } from "next";
import type { JSX, ReactNode } from "react";
// eslint-disable-next-line import/no-unassigned-import -- Import global styles.
import "./globals.css";
// eslint-disable-next-line new-cap -- This is a function call.
const inter = Inter({ subsets: [ "latin" ] });
const metadata: Metadata = {
description:
"This page tells you everything you could ever want to know about Naomi and her consulting firm nhcarrigan.",
openGraph: {
images: "https://cdn.nhcarrigan.com/og-image.png",
},
title: "NHCarrigan Announcements",
twitter: {
card: "summary_large_image",
images: "https://cdn.nhcarrigan.com/og-image.png",
site: "@naomi_lgbt",
},
};
/**
* The top-level wrapper for the React application.
* Handles mounting the shadow DOM.
* @param opts - The rendering options.
* @param opts.children - The children elements to render.
* @returns A JSX element.
*/
const RootLayout = ({
children,
}: Readonly<{
children: ReactNode;
}>): JSX.Element => {
return (
<html lang="en">
<Script
async={true}
defer={true}
src="https://cdn.nhcarrigan.com/headers/index.js"
strategy={"afterInteractive"}
type="text/javascript"
></Script>
<link
href="https://cdn.nhcarrigan.com/logo.png"
rel="icon"
sizes="any"
/>
<body className={inter.className}>
{children}
</body>
</html>
);
};
export { metadata };
export default RootLayout;

View File

@ -1,26 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Rule } from "@/components/rule";
import { getSortedPostsData } from "@/lib/posts";
export default function Home() {
const posts = getSortedPostsData();
return (
<main>
<h1>{"Announcements"}</h1>
<p>{"This page documents all of our organisation's announcements, in reverse chronological order."}</p>
{posts.map((post) => {
return <div key={post.slug}>
<Rule />
<h2><a className="underline" href={`/post/${post.slug}`}>{post.data.title}</a></h2>
<p className="italic text-center">{post.data.date.toLocaleDateString("en-GB",{ year: "numeric", month: "long", day: "numeric"})}</p>
<p>{post.data.summary}</p>
</div>;
})}
</main>
);
}

View File

@ -1,23 +0,0 @@
import { Rule } from "@/components/rule";
import { getPostData } from "@/lib/posts";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
export default async function Page({
params
}: {
params: Promise<{slug: string}>
}) {
const { slug } = await params;
const post = getPostData(slug);
return (
<main>
<h1>{post.data.title}</h1>
<p className="italic text-center">{`Published ${post.data.date.toLocaleDateString("en-GB", { weekday: "long", year: "numeric", month: "long", day: "numeric"})}`}</p>
<Rule />
<Markdown remarkPlugins={[remarkGfm]}>{post.content}</Markdown>
<Rule />
<a href="/">{"← Back to home"}</a>
</main>
)
}

View File

@ -1,14 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
/**
* Renders a customised horizontal rule.
* @returns A JSX element.
*/
export const Rule = (): JSX.Element => {
return <hr className="border-dashed border-2 border-[--primary-color]"></hr>;
};

View File

@ -1,58 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { readFileSync, readdirSync } from "node:fs";
import { join } from "node:path";
import matter from "gray-matter";
const postsDirectory = join(process.cwd(), "posts");
export const getSortedPostsData = () => {
const fileNames = readdirSync(postsDirectory);
const allPostsData = fileNames.map((fileName) => {
const slug = fileName.replace(/\.md$/, "");
const fullPath = join(postsDirectory, fileName);
const fileContents = readFileSync(fullPath, "utf8");
const matterResult = matter(fileContents) as unknown as {
content: string;
data: { title: string; date: string; summary: string };
};
return {
slug: slug,
data: {
title: matterResult.data.title,
date: new Date(matterResult.data.date),
summary: matterResult.data.summary,
},
content: matterResult.content,
};
});
return allPostsData.sort((a, b) => {
if (a.data.date < b.data.date) {
return 1;
} else {
return -1;
}
});
};
export const getPostData = (slug: string) => {
const fullPath = join(postsDirectory, slug + ".md");
const fileContents = readFileSync(fullPath, "utf8");
const matterResult = matter(fileContents) as unknown as {
content: string;
data: { title: string; date: string; summary: string };
};
return {
slug: slug,
data: {
title: matterResult.data.title,
date: new Date(matterResult.data.date),
summary: matterResult.data.summary,
},
content: matterResult.content,
};
}

View File

@ -1,18 +0,0 @@
import type { Config } from "tailwindcss";
export default {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
},
},
},
plugins: [],
} satisfies Config;

View File

@ -1,27 +0,0 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}