{"id":24834650,"url":"https://github.com/na-trium-144/falling-nikochan","last_synced_at":"2025-08-02T04:34:34.251Z","repository":{"id":253366539,"uuid":"843038370","full_name":"na-trium-144/falling-nikochan","owner":"na-trium-144","description":"Simple and cute rhythm game, where anyone can create and share charts.","archived":false,"fork":false,"pushed_at":"2025-08-01T23:46:23.000Z","size":6318,"stargazers_count":2,"open_issues_count":53,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-02T01:22:56.493Z","etag":null,"topics":["html5","mongodb","nextjs","pwa","pwa-apps","react","rhythm-game","youtube"],"latest_commit_sha":null,"homepage":"https://nikochan.utcode.net/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/na-trium-144.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG_dev.md","contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2024-08-15T16:42:06.000Z","updated_at":"2025-07-29T18:43:41.000Z","dependencies_parsed_at":"2024-08-16T08:48:46.143Z","dependency_job_id":"68b868e8-d9ba-4b07-a21d-cc4fa16f7457","html_url":"https://github.com/na-trium-144/falling-nikochan","commit_stats":null,"previous_names":["na-trium-144/falling-nikochan"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/na-trium-144/falling-nikochan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/na-trium-144%2Ffalling-nikochan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/na-trium-144%2Ffalling-nikochan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/na-trium-144%2Ffalling-nikochan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/na-trium-144%2Ffalling-nikochan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/na-trium-144","download_url":"https://codeload.github.com/na-trium-144/falling-nikochan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/na-trium-144%2Ffalling-nikochan/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268334622,"owners_count":24233793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["html5","mongodb","nextjs","pwa","pwa-apps","react","rhythm-game","youtube"],"created_at":"2025-01-31T03:33:15.871Z","updated_at":"2025-08-02T04:34:34.242Z","avatar_url":"https://github.com/na-trium-144.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Falling Nikochan\n\n* Simple and cute rhythm game. Playable on web browsers such as PC, tablet, and smartphone.\n* Anyone can create a chart without any account registration or login. Share the chart ID on SNS to let others play.\n* Uses YouTube embed as audio source.\n\nFor more information, play, and chart creation, please visit the [Falling Nikochan top page](https://nikochan.utcode.net).\n\n\u003e * シンプルでかわいい音ゲーです。PC、タブレット、スマートフォンなどのブラウザーで手軽に遊べます。\n\u003e * さらに、アカウント登録やログイン不要で誰でも譜面を作成でき、SNSなどで譜面IDを共有することで他の人に遊んでもらうことができます。\n\u003e * 音源としてYouTube埋め込みを利用しています。\n\u003e\n\u003e 遊び方などの説明、プレイ、譜面作成 は、 [Falling Nikochan トップページ](https://nikochan.utcode.net) からどうぞ。\n\nYouTube: [@nikochan144](http://www.youtube.com/@nikochan144)\n\n[\u003cimg src=\"https://github.com/na-trium-144/falling-nikochan/blob/main/.github/screenshot.jpg?raw=true\" width=960 /\u003e](https://www.youtube.com/watch?v=reUvjq5TRus)\n\n## Development\n\n* Install [Node.js](https://nodejs.org/ja/download) (\u003e=20) or [Bun](https://bun.sh/docs/installation) (\u003e=1.2).\n* Install [MongoDB](https://www.mongodb.com/docs/manual/installation/) and run on `localhost:27017`\n    * If you have Docker installed, it is easy to run and recommended\n        ```sh\n        docker run --rm -p 27017:27017 -d mongodb/mongodb-community-server:latest\n        ```\n        * or `npm run mongo-docker`, `bun mongo-docker` does the same.\n    * Falling Nikochan creates and uses a database named `nikochan` in it\n* Create a `.env` file with the following contents\n    ```sh\n    MONGODB_URI=\"mongodb://localhost:27017\"\n    BACKEND_PREFIX=\"http://localhost:8787\"\n    API_ENV=\"development\"\n    API_NO_RATELIMIT=\"1\"\n    ```\n    * other environment variables:\n        * `SECRET_SALT` (backend): string\n        * `VERCEL_PROTECTION_BYPASS_SECRET` (backend): string\n        * `API_CACHE_EDGE` (backend): `1` or unset\n        * `ASSET_PREFIX` (backend \u0026 frontend): `https://domain-of-your-assets/` or unset\n        * `BACKEND_PREFIX` (frontend): `https://domain-of-your-backend/` or unset\n        * `BACKEND_OG_PREFIX` (backend): alternate backend for og image generation, `https://domain-of-your-backend/` or unset\n        * `NO_PREFETCH` (frontend): `1` or unset\n        * `GOOGLE_API_KEY` (backend): API key for YouTube Data API v3 (optional)\n* Install dependencies\n    ```sh\n    npm ci  # or  bun i\n    ```\n    * [GitHub Action ensures](.github/workflows/sync-lock.yaml) the two lockfiles synchronized with package.json.\n* Common files (chart/)\n    * When you make any changes, you need to run tsc to re-compile them into js files so that they can be imported correctly in the frontend and backend:\n        ```sh\n        npm run t  # or  bun t\n        ```\n* Backend\n    * Serves /api, /share, /og, and / (redirect).\n    * Built with Hono, so it can be run with many runtimes.\n    * For a local development environment, server can be run with Node.js or Bun (`http://localhost:8787`)\n        ```sh\n        npm run ldev  # or  bun bdev\n        ```\n    * For the deployment, currently using Cloudflare Worker and Vercel\n* Frontend\n    * development environment of Next.js (`http://localhost:3000/ja` or `/en`)\n        * Doing SSR for the path `/share/[cid]` by the backend modifying the exported html file, so this page does not work in the development environment.\n        * Instead, `/ja/share/placeholder` shows the placeholder page.\n        ```sh\n        npm run ndev  # or  bun ndev\n        ```\n    * Or, SSR with exported html files\n        * All pages should work by accessing the backend (`http://localhost:8787`) after building frontend, but there is no hot-reload.\n        ```sh\n        npm run nbuild \u0026\u0026 npm run swbuild\n        # or  bun nbuild \u0026\u0026 bun swbuild\n        ```\n    * As of Bun v1.2.2, `bun -b nbuild` seems to be unstable for this project.\n* Service Worker\n    * Build frontend and service worker\n    ```sh\n    npm run nbuild \u0026\u0026 npm run swbuild\n    # or  bun nbuild \u0026\u0026 bun swbuild\n    ```\n    * Access the backend (`http://localhost:8787`) to see the service worker in action\n    * The service worker ([worker/entry.ts](worker/entry.ts) bundled into /sw.js) fetches and stores all the assets and the pages, except for /api and /og.\n        * it modifies asset urls in html and js sources so that they will always use assets from the cache.\n        * it will update the cache every time /assets/buildVer.json (generated by [frontend/next.config.mjs](frontend/next.config.mjs)) has changed.\n        * it uses custom languageDetector middleware based on `navigator.languages` to determine the language of the page, since the Accept-Language header does not work.\n\n## API\n\nThe code for the backend is in the [route/](route/) directory, NOT in the [api/](api/) directory.\n\n\u003cdetails\u003e\u003csummary\u003eAPI List\u003c/summary\u003e\n\nSee also [chart/src/chart.ts](chart/src/chart.ts) for relations among the chart data formats.\n\n* `GET /api/brief/:cid` - Get the brief information of the chart.\n    * `:cid` - Chart ID\n    * Response\n        * [ChartBrief](chart/src/chart.ts) as JSON with status code 200\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * 404 (cid not found),\n            * or 500 (other error)\n* `GET /api/latest` - Get the list of 24 latest updated charts.\n    * Response\n        * `{cid: string}[]` as JSON with status code 200\n* `GET /api/popular` - Get the list of 24 popular charts.\n    * Response\n        * `{cid: string, count: number}[]` as JSON with status code 200\n* `GET /api/record/:cid` - Get the summary of the record from all players for the chart.\n    * `:cid` - Chart ID\n    * Response\n        * Array of [RecordGetSummary](chart/src/record.ts) as JSON with status code 200\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * or 500 (other error)\n* `POST /api/record/:cid` - Post a play record to the database. The record for every play is stored.\n    * `:cid` - Chart ID\n    * Request Body\n        * [RecordPost](chart/src/record.ts) as JSON\n            * The data should be the record of the current play of the player, regardless of the best score etc.\n    * Response\n        * empty response with status code 204\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * or 500 (other error)\n* `GET /api/seqFile/:cid/:lvIndex` - Deprecated. Returns 410.\n* `GET /api/playFile/:cid/:lvIndex` - Get the level file. Used only when playing chart, not for editing.\n    * `:cid` - Chart ID\n    * `:lvIndex` - Level index number\n    * Response\n        * [Level6Play](chart/src/legacy/chart6.ts) or [Level11Play](chart/src/legacy/chart11.ts) serialized with MessagePack with status code 200\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * 404 (cid or level not found),\n            * or 500 (other error)\n* `GET /api/hashPasswd/:cid` - Get the unique hash of the password for the chart.\n    * `:cid` - Chart ID\n    * Query Parameters\n        * `cp=` sha256 hash of (cid + passwd)\n    * if `pUserSalt` value is not in the cookie, a random string is generated and stored.\n    * Response\n        * sha256 hash of (cid + passwd + hashKey) as raw text with status code 200\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * 401 (wrong passwd),\n            * 404 (cid not found),\n            * or 500 (other error)\n* `GET /api/chartFile/:cid` - Get the chart file. Password is required.\n    * `:cid` - Chart ID\n    * Query Parameters\n        * Either one of the following is required.\n            * `cp=` sha256 hash of (cid + passwd)\n            * `ph=` hash of passwd obtained from `/api/hashPasswd/:cid?cp=...`\n                * The cookie value `pUserSalt` must be set and match with that used for the hash.\n            * `pbypass=1` (only on development environment) bypass the password check\n    * Response\n        * [Chart4](chart/src/legacy/chart4.ts), [Chart5](chart/src/legacy/chart5.ts), [Chart6](chart/src/legacy/chart6.ts), [Chart7](chart/src/legacy/chart7.ts), [Chart8Edit](chart/src/legacy/chart8.ts), [Chart9Edit](chart/src/legacy/chart9.ts) or [Chart11Edit](chart/src/legacy/chart11.ts) serialized with MessagePack with status code 200\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * 401 (wrong passwd),\n            * 404 (cid not found),\n            * or 500 (other error)\n* `POST /api/chartFile/:cid` - Post the chart file. The previous password is required. If the posted chart data has a different password, it will be used next time.\n    * `:cid` - Chart ID\n    * Query Parameters: same as GET\n    * Request Body: [Chart11Edit](chart/src/legacy/chart11.ts) serialized with MessagePack\n    * Response\n        * empty response with status code 204\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * 401 (wrong passwd),\n            * 404 (cid not found),\n            * 409 (chart data is Chart9 or older),\n            * 413 (too large),\n            * 415 (invalid data),\n            * or 500 (other error)\n* `DELETE /api/chartFile/:cid` - Delete the chart file. Password is required.\n    * `:cid` - Chart ID\n    * Query Parameters: same as GET\n    * Response\n        * empty response with status code 204\n        * `{message?: string}` as JSON with status code\n            * 400 (invalid cid),\n            * 401 (wrong passwd),\n            * 404 (cid not found),\n            * or 500 (other error)\n* `GET /api/newChartFile` - returns 400.\n* `POST /api/newChartFile` - Create a new chart file.\n    * Request Body: [Chart11Edit](chart/src/legacy/chart11.ts) serialized with MessagePack\n    * Response\n        * `{cid: string}` as JSON with status code 200\n        * `{message?: string}` as JSON with status code\n            * 409 (chart data is Chart11 or older),\n            * 413 (too large),\n            * 415 (invalid data),\n            * 429 (rate limited),\n            * or 500 (other error)\n\n\u003c/details\u003e\n\n## Localization\n\n[i18n/](i18n/) directory contains the translations of the application.\n\nTo add a new language, create a new directory with the language code and add all the translations in the corresponding files.\n\nSee also [next-intl Usage guide](https://next-intl.dev/docs/usage/messages)\n\n## Versioning\n\n* major version follows the Chart data format version.\n* minor version is increased by `npm version -ws minor` command for each PR\n    * Changes that do not affect app/ such as dependabot or update README.md are not counted.\n* ChangeLogs are written in [i18n/[locale]/changelog.mdx](i18n/ja/changelog.mdx) for user-friendly explanation and in [CHANGELOG_dev.md](CHANGELOG_dev.md) for more detailed explanation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fna-trium-144%2Ffalling-nikochan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fna-trium-144%2Ffalling-nikochan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fna-trium-144%2Ffalling-nikochan/lists"}