{"id":49191477,"url":"https://github.com/moikapy/moikapy-dev","last_synced_at":"2026-04-23T07:01:30.780Z","repository":{"id":350560393,"uuid":"1207384509","full_name":"Moikapy/moikapy-dev","owner":"Moikapy","description":"Personal blog \u0026 site for moikapy.dev — AI engineer, gamer, 3D printing","archived":false,"fork":false,"pushed_at":"2026-04-10T22:37:41.000Z","size":319,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"feat/tiptap-pwa-mobile","last_synced_at":"2026-04-11T00:15:46.401Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Moikapy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-10T22:08:56.000Z","updated_at":"2026-04-10T22:09:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Moikapy/moikapy-dev","commit_stats":null,"previous_names":["moikapy/moikapy-dev"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Moikapy/moikapy-dev","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moikapy%2Fmoikapy-dev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moikapy%2Fmoikapy-dev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moikapy%2Fmoikapy-dev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moikapy%2Fmoikapy-dev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Moikapy","download_url":"https://codeload.github.com/Moikapy/moikapy-dev/tar.gz/refs/heads/feat/tiptap-pwa-mobile","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moikapy%2Fmoikapy-dev/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32169657,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T02:19:40.750Z","status":"ssl_error","status_checked_at":"2026-04-23T02:17:55.737Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-23T07:01:29.607Z","updated_at":"2026-04-23T07:01:30.726Z","avatar_url":"https://github.com/Moikapy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# moikapy.dev\n\nPersonal blog of **moikapy** — AI Engineer x Gamer.\n\nBuilt with **Next.js 16**, **Tailwind CSS v4**, and **shadcn/ui**. Deployed on **Cloudflare Pages** with **Cloudflare D1** for blog post storage.\n\n## Features\n\n- 📝 Blog with admin panel — write and publish from any device at `/admin`\n- 🔐 Password-protected admin — login from your phone, tablet, anywhere\n- 🗄️ **Cloudflare D1** database — no git commits needed to publish posts\n- 📡 RSS feed at `/feed/rss.xml`\n- ⚡ Nostr feed at `/feed/nostr.json` (NIP-23 long-form content)\n- 🌑 Dark mode by default\n- 🔍 SEO optimized (sitemap, robots.txt, Open Graph)\n- 🚀 Deployed on Cloudflare with OpenNext\n\n## Setup\n\n### 1. Install dependencies\n\n```bash\nbun install\n```\n\n### 2. Create the D1 database\n\n```bash\nbunx wrangler login\nbun run db:create\n```\n\nCopy the `database_id` from the output and paste it into `wrangler.toml`:\n\n```toml\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"moikapy-blog\"\ndatabase_id = \"YOUR_ID_HERE\"\n```\n\n### 3. Set up admin authentication\n\nGenerate a password hash:\n\n```bash\nbun run auth:hash-password your-password-here\n```\n\nThis outputs something like `ADMIN_PASSWORD_HASH=abc123...`. Set it as a Cloudflare secret:\n\n```bash\n# Set the password hash\nwrangler secret put ADMIN_PASSWORD_HASH\n# Paste the hash when prompted\n\n# Generate and set a session signing secret\nopenssl rand -hex 32\nwrangler secret put SESSION_SECRET\n# Paste the generated hex string\n```\n\nFor local development, add both to `.env.local`:\n\n```\nADMIN_PASSWORD_HASH=your-hash-here\nSESSION_SECRET=your-random-hex-here\n```\n\n### 4. Run the migrations\n\n```bash\nbun run db:migrate:local     # Local development\nbun run db:migrate:remote    # Production (after first deploy)\n```\n\n### 5. Local development\n\n```bash\nbun run dev        # Next.js dev server (no D1 — admin/blog won't fully work)\nbun run preview     # Cloudflare dev server with D1 (full stack)\n```\n\n### 6. Deploy\n\n```bash\nbun run build\nbun run build:cf\nbun run deploy\n```\n\n## Writing Posts\n\n### From the admin panel\n\n1. Visit `moikapy.dev/admin`\n2. Enter your password\n3. Click \"+ New Post\"\n4. Write your post in markdown, add tags, toggle \"Published\"\n5. Save — it's live\n\nWorks on any device — phone, tablet, laptop.\n\n### Via the API\n\n```bash\n# Create a post (needs session cookie from login)\ncurl -X POST https://moikapy.dev/api/posts \\\n  -H \"Content-Type: application/json\" \\\n  -b cookies.txt \\\n  -d '{\n    \"slug\": \"my-post\",\n    \"title\": \"My Post\",\n    \"excerpt\": \"A short description\",\n    \"content\": \"# Hello\\n\\nThis is my post...\",\n    \"tags\": [\"ai\", \"gaming\"],\n    \"published\": true\n  }'\n\n# Update a post\ncurl -X PATCH https://moikapy.dev/api/posts/my-post \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"published\": false}'\n\n# Delete a post\ncurl -X DELETE https://moikapy.dev/api/posts/my-post\n```\n\n## Nostr Publishing\n\n### Generate a key pair (one-time)\n\n```bash\nbun run nostr:generate-keys\n```\n\nSave the `nsec` to `.env` and add the `npub` to `src/lib/config.ts`.\n\n### Publish posts to Nostr relays\n\n```bash\nNSEC=nsec1... bun run nostr:publish\n```\n\n## Storage\n\n| What | Where | Why |\n|------|-------|-----|\n| Blog posts | **Cloudflare D1** (SQLite) | Write from anywhere, no git required |\n| Images/media | Cloudflare R2 (optional) | S3-compatible, zero egress fees |\n\n## Auth Architecture\n\n- **Password**: SHA-256 hashed, stored as Cloudflare secret (`ADMIN_PASSWORD_HASH`)\n- **Session**: HMAC-SHA256 signed token, stored in httpOnly cookie (7 day expiry)\n- **Protected routes**: `/admin/*` (redirects to `/admin/login`) and `/api/posts/*` (returns 401)\n- **Public routes**: Blog pages, RSS, Nostr, login page\n\n## Project Structure\n\n```\n├── drizzle/              # D1 migration SQL\n├── scripts/              # Auth, Nostr, key generation\n├── src/\n│   ├── app/\n│   │   ├── admin/        # Admin panel (login + post editor)\n│   │   ├── api/\n│   │   │   ├── auth/     # Login/logout API\n│   │   │   └── posts/    # REST API for posts CRUD\n│   │   ├── blog/         # Public blog pages\n│   │   └── feed/         # RSS + Nostr feed endpoints\n│   ├── components/       # React components\n│   ├── db/               # Drizzle ORM + D1 schema\n│   └── lib/              # Config, auth, posts API\n├── middleware.ts         # Auth middleware (protects admin + API)\n├── open-next.config.ts   # Cloudflare OpenNext config\n└── wrangler.toml         # Cloudflare Workers config\n```\n\n## Scripts\n\n| Command | Description |\n|---------|-------------|\n| `bun run dev` | Next.js dev server |\n| `bun run preview` | Cloudflare dev server (with D1) |\n| `bun run build` | Production build |\n| `bun run build:cf` | Build for Cloudflare |\n| `bun run deploy` | Deploy to Cloudflare |\n| `bun run db:create` | Create D1 database |\n| `bun run db:migrate:local` | Run migrations locally |\n| `bun run db:migrate:remote` | Run migrations on production D1 |\n| `bun run auth:hash-password` | Hash a password for admin login |\n| `bun run nostr:generate-keys` | Generate Nostr key pair |\n| `bun run nostr:publish` | Publish posts to Nostr relays |","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoikapy%2Fmoikapy-dev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoikapy%2Fmoikapy-dev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoikapy%2Fmoikapy-dev/lists"}