Skip to content
105 changes: 105 additions & 0 deletions .agents/skills/github-issue-create/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
name: github-issue-create
description: >-
Creates a new GitHub issue using the GitHub CLI (gh issue create): title,
body, labels, assignees, milestone, template, or target repo. Use when the
user asks to open, file, or create a GitHub issue via gh; wants gh issue new;
or says to track work on GitHub without an existing issue number.
---

# GitHub issue create (gh CLI)

## When this applies

Use when the user wants a **new** issue recorded on GitHub and agrees to use **`gh`** (not only local notes). If they only want a draft, produce markdown they can paste instead of running `gh`.

## Prerequisites

- `gh` installed and authenticated: `gh auth status` (else `gh auth login`).
- Network access when running `gh`.
- Prefer the **git repo root** so the default remote matches the intended repository.
- Another repo: pass `-R owner/repo` (or `HOST/owner/repo` for GitHub Enterprise).

## 1. Gather content

Before running `gh`, confirm:

- **Title** — short, imperative or problem-focused (e.g. “Profile articles tab shows blank when empty”).
- **Body** — context, steps to reproduce, expected vs actual, screenshots/links as markdown. Do **not** paste secrets, tokens, or full `.env` contents.

Optional metadata from the user:

- **Labels** (`-l`): repeat per label or comma-separated per `gh` examples.
- **Assignee** (`-a`): logins or `@me`.
- **Milestone** (`-m`): exact name as on GitHub.
- **Project** (`-p`): project title; requires `gh auth refresh -s project` if GitHub returns project permission errors.
- **Template** (`-T`): must match a template filename in `.github/ISSUE_TEMPLATE/` (if the repo uses them).

## 2. Create the issue

**Simple (inline):**

```bash
gh issue create --title "Your title" --body "Your body (markdown OK in quotes; use a file for long text)."
```

**Long body or complex markdown — use a file:**

```bash
gh issue create --title "Your title" --body-file path/to/issue-body.md
```

**Stdin:**

```bash
gh issue create --title "Your title" --body-file -
# then paste body, end with Ctrl-D
```

**Labels and self-assign:**

```bash
gh issue create -t "Title" -b "Body" -l bug -l "help wanted" -a "@me"
```

**Editor (title + body in one buffer — first line is title):**

```bash
gh issue create -e
```

**Web UI:**

```bash
gh issue create -w
```

**Explicit repo:**

```bash
gh issue create -R owner/repo -t "Title" -b "Body"
```

**From template:**

```bash
gh issue create --template "Bug Report"
```

Alias: `gh issue new` is equivalent to `gh issue create`.

## 3. After create

`gh` prints the new issue URL. Share it with the user. Optionally mention the related skill for fixing issues: `github-issue-resolve`.

## Safety

- Do **not** run `gh issue create` without a clear title and body the user (or task) actually wants on the public tracker.
- If intent is ambiguous, ask once for title, body, and labels before creating.

## Checklist

- [ ] Title and body ready; no secrets in the body.
- [ ] Correct repo (`cwd` or `-R`).
- [ ] Labels / assignee / milestone / project / template applied if requested.
- [ ] Command run; URL returned to the user.
102 changes: 102 additions & 0 deletions .agents/skills/github-issue-resolve/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
name: github-issue-resolve
description: >-
Resolves a numbered GitHub issue using the GitHub CLI (gh): fetch full
context, implement the fix, then post a structured summary comment on the
issue. Use when the user asks to fix, solve, or implement a GitHub issue by
number; mentions gh issue view or GitHub CLI for issues; or says to comment
back on the issue after fixing.
---

# GitHub issue resolve (gh CLI)

## When this applies

Use this workflow when the user gives an issue number (e.g. “fix #57”, “solve issue 42”) and expects the work tracked on GitHub with a **comment**, not only local code changes.

## Prerequisites

- `gh` installed and authenticated: `gh auth status` (if it fails, run `gh auth login`).
- Shell with `network` permission when calling `gh`.
- Run `gh` from the **git repo root** so `gh issue view` targets the correct repository.

## 1. Load the issue

Always fetch the issue before coding so title, body, labels, and images/links are grounded in real data.

```bash
gh issue view <N>
```

Useful additions:

```bash
gh issue view <N> --json title,body,state,labels,assignees,comments --jq .
```

If discussion matters:

```bash
gh issue view <N> --comments
```

**Images in the body**: GitHub stores them as URLs; open or fetch if the visual is required to understand the bug.

## 2. Implement the fix

- Follow the repo’s normal patterns (read surrounding code first; minimal diff).
- Run targeted checks (e.g. `eslint` on touched files, `bun run build` if appropriate). Fix anything **introduced** by the change.

## 3. Summary for GitHub (before commenting)

Draft a short, professional summary the maintainer can skim:

- **What** was wrong (1–2 sentences, tied to the issue).
- **What changed** (bullet list of files or areas; no huge pasted code).
- **How to verify** (e.g. steps or pages to open).
- Optional: **Follow-ups** only if truly out of scope.

Do **not** include secrets, tokens, `.env` values, or internal-only URLs in the comment.

## 4. Post the comment on the issue

Post the summary as an **issue comment** (does not close the issue unless the user asked to close it).

**Option A — body from stdin:**

```bash
gh issue comment <N> --body "$(cat <<'EOF'
## Summary

[your markdown here]
EOF
)"
```

**Option B — file:**

Write the body to a temp file, then:

```bash
gh issue comment <N> --body-file /path/to/comment.md
```

Prefer markdown headings (`##`) and bullets for readability.

## 5. Close the issue (only if asked)

If the user explicitly wants the issue closed after the fix:

```bash
gh issue close <N> --comment "Fixed in [branch/PR description]. See comment above for details."
```

Otherwise leave it **open** for human review or PR merge.

## Checklist

- [ ] Fetched issue with `gh issue view` (and JSON/comments if needed).
- [ ] Implemented and validated the change locally.
- [ ] Wrote a concise summary (no secrets).
- [ ] Posted `gh issue comment <N>`.
- [ ] Closed the issue only if the user requested it.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ This project adheres to [Semantic Versioning](https://semver.org/).

---

## v1.5.0 — 2026-04-01

### ✨ Features
- feat: enhance NavbarActions with dropdown menu for creating new entries (eb652b2)
- feat: add unpublished article notice and draft byline support (4528d1a)
- feat: enhance profile page with additional user information and improved article loading states (2458ad7)
- feat: improve user profile experience with enhanced data display and loading states (3dedc30)
- feat: enhance user profile with additional fields and improved loading states (2db6598)
- feat: improve user avatar handling and display in LatestUsers component (ea1fe57)

### 🔧 Other Changes
- refactor: update theme handling and improve layout structure (524ebc4)

---

## v1.4.0 — 2026-03-30

### ✨ Features
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "techdiary.dev-next",
"version": "1.4.0",
"version": "1.5.0",
"private": true,
"scripts": {
"dev": "next dev --turbo",
Expand Down Expand Up @@ -58,7 +58,6 @@
"meilisearch": "^0.51.0",
"modern-screenshot": "^4.6.8",
"next": "^16.2.1",
"next-themes": "^0.4.6",
"pg": "^8.14.1",
"react": "^19",
"react-advanced-cropper": "^0.20.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ const ProfilePageAside: React.FC<ProfilePageAsideProps> = ({ profile }) => {
<p className="my-2 text-sm text-muted-foreground">{profile?.bio}</p>
)}

{profile?.skills && (
<p className="my-2 text-sm">
<span className="font-medium text-foreground">Skills: </span>
<span className="text-muted-foreground">{profile.skills}</span>
</p>
)}

{/* User infos start */}
<div className="flex flex-col mt-4 gap-2 md:gap-4">
{profile?.website_url && (
Expand Down
41 changes: 36 additions & 5 deletions src/app/[username]/(profile-page)/articles/UserArticleFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
"use client";

import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import { useInfiniteQuery } from "@tanstack/react-query";
import * as articleActions from "@/backend/services/article.actions";
import React, { useMemo } from "react";
import ArticleCard from "@/components/ArticleCard";
import { readingTime } from "@/lib/utils";
import VisibilitySensor from "@/components/VisibilitySensor";
import getFileUrl from "@/utils/getFileUrl";
import { useTranslation } from "@/i18n/use-translation";
import Image from "next/image";

interface UserArticleFeedProps {
userId: string;
}

const UserArticleFeed: React.FC<UserArticleFeedProps> = ({ userId }) => {
const { _t } = useTranslation();

const feedInfiniteQuery = useInfiniteQuery({
queryKey: ["user-article-feed", userId],
queryFn: ({ pageParam }) =>
Expand Down Expand Up @@ -42,22 +46,49 @@ const UserArticleFeed: React.FC<UserArticleFeedProps> = ({ userId }) => {
});

const feedArticles = useMemo(() => {
return feedInfiniteQuery.data?.pages.flatMap((page) => page?.nodes);
return feedInfiniteQuery.data?.pages.flatMap((page) => page?.nodes) ?? [];
}, [feedInfiniteQuery.data]);

const showEmpty =
!feedInfiniteQuery.isPending &&
!feedInfiniteQuery.isError &&
feedArticles.length === 0;

return (
<>
{feedInfiniteQuery.isFetching && (
{feedInfiniteQuery.isPending && (
<div className="flex flex-col gap-10 pt-4">
{Array.from({ length: 6 }).map((_, index) => (
<div key={index} className="h-56 bg-muted animate-pulse mx-4" />
))}
</div>
)}

{/* <pre>{JSON.stringify(feedArticles, null, 2)}</pre> */}
{feedInfiniteQuery.isError && (
<div className="py-10 px-4 text-center text-sm text-muted-foreground">
{_t("Could not load articles.")}
</div>
)}

{showEmpty && (
<div className="py-10 flex flex-col items-center justify-center gap-4 px-4">
<Image
src="/images/robots-drones-artificial-intelligence-1.png"
alt=""
width={220}
height={220}
className="mx-auto opacity-90"
/>
<h2 className="text-xl font-semibold text-center">
{_t("No articles published yet")}
</h2>
<p className="text-sm text-muted-foreground text-center max-w-md">
{_t("When this user publishes articles, they will show up here.")}
</p>
</div>
)}

{feedArticles?.map((article) => (
{feedArticles.map((article) => (
<ArticleCard
key={article?.id}
id={article?.id ?? ""}
Expand Down
7 changes: 5 additions & 2 deletions src/app/[username]/(profile-page)/articles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ const Page: React.FC<PageProps> = async ({ params }) => {
const username = sanitizedUsername(_params?.username);
const profile = await getUserByUsername(username, ["id", "username"]);

if (!profile?.id) {
return null;
}

return (
<main className="border rounded-bl-2xl rounded-br-2xl md:col-span-9 col-span-full mt-3">
{/* <pre>{JSON.stringify(profile, null, 2)}</pre> */}
<UserArticleFeed userId={profile?.id!} />
<UserArticleFeed userId={profile.id} />
</main>
);
};
Expand Down
10 changes: 8 additions & 2 deletions src/app/[username]/(profile-page)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,21 @@ const layout: React.FC<ProfilePageLayoutProps> = async ({
const _params = await params;
const username = sanitizedUsername(_params?.username);
const profile = await getUserByUsername(username, [
// all fields
"id",
"name",
"username",
"email",
"profile_photo",
"bio",
"designation",
"website_url",
"education",
"location",
"social_links",
"skills",
"is_verified",
"created_at",
"updated_at",
"social_links",
]);

if (!profile) {
Expand Down
Loading