not/onの公開記事をより、止まらせず(NOT DO NE)、動く(ALWAYS ON)ものにするため、ダイナミックな記事生成のパーツを検討する。
funkApiCoreは、これを実現するにあたり、not/onエンジンが呼び出すライブラリとして作成する。
not/onのコンセプトはこちらから。
ちなみにfunkApiCoreはCORSフリー、誰でもどのAPPでも自由に使える。
下記にそのコンセプト、想定利用内容、および呼び出し方法についてまとめていく。
funkApiCore 開発ドキュメント
funkApiCore は、記事やブログの投稿サービスにおいて、テキスト内に埋め込まれたカスタム構文(予約語)を検知し、動的なコンテンツ(お天気情報、祝日、最寄り駅、名言など)をパブリックAPIから取得してJSON形式で返却するための完全独立型JavaScript共通APIラッパーライブラリ。
1. コンセプト
⚙️ CORSフリー & ANTI-STACK
本ライブラリは、ブラウザのDOM(画面描画)や他のライブラリやフレームワークに依存しないピュアJavaScript(ES6)で記述。
極力開発環境や実行環境をスタックしない、下記、ANTI-STACKポリシーに準拠
また、利用するすべてのパブリックAPI(Open-Meteo, HeartRails, DummyJSON等)はCORSポリシーに対応しており、HTTPS環境下(https://noton.youside.me 等)からブラウザの fetch で直接呼び出してもブロックされない安全なアーキテクチャを採用する。
📊 レスポンスの標準化
各APIのバラバラなデータ構造を吸収し、常に以下の統一されたJSON形式で結果を返却する。
- 成功時:
{ status: "success", data: { ... } } - 失敗時:
{ status: "error", error: { code: "...", message: "..." } }
🌐 多言語への柔軟性(日英併記)
海外のAPIから返却される英語の気象ステータスなどは、ライブラリ内部で日本語(weather_text_ja)と英語(weather_text_en)の両方にマッピングして応答。
アーキテクチャ
2. 想定利用内容(使われ方)
本ライブラリは、not/on(記事投稿サービス)における「動的ブログパーツ(埋め込みコンポーネント)」のバックエンドロジックとしての利用を想定。
ただし、誰でもどのAPPでも使える。
記事内の記述例(疑似タグスタイル):
今日の世田谷はとても過ごしやすい気候です。
[WEATHER lat="35.65" lng="139.54" date="today"]ここが最寄りになります。
[NEAREST_STATION]今日の名言:
[TRIVIA type="zen"]
レンダリングの流れ:
- エンジン側のパーサーが記事内の予約語を検知し、UIの「枠(プレースホルダー)」を画面に描画します。
- UI層のJavaScriptが、タグから抽出した属性値(
lat,lngなど)を引数に渡し、本ライブラリ(FunkApiCore)を実行します。 - 返却された標準化JSONのデータを、UI層がHTMLに流し込んで装飾します。
3. 呼び出し方法(使い方と関数の紹介)
import { FunkApiCore } from './funkApiCore.js';
① 天気情報の取得(WEATHER)
特定地点の特定時間の天気を取得できる。
const response = await FunkApiCore.getWeather(35.65, 139.54, "today");
if (response.status === "success") {
console.log(response.data.weather_text_ja); // 例: "霧雨"
console.log(`${response.data.temp_max}℃`); // 例: "24.9℃"
}
② 祝日情報の取得(HOLIDAY)
日本の祝日情報を取得できる。
"next"(直近)、"this_month"(今月)、"next_month"(来月)を指定。
const response = await FunkApiCore.getHolidays("next");
if (response.status === "success") {
console.log(response.data.holidays[0].name); // 例: "海の日"
}
③ 最寄り駅情報の取得(NEAREST_STATION)
特定の位置情報を渡すと、最寄駅の情報を返す。
特定の位置情報は、クライアントから送ってもらうことを想定。
const response = await FunkApiCore.getNearestStation(35.65, 139.54);
if (response.status === "success") {
const st = response.data;
console.log(`${st.line_name} ${st.station_name}駅 (徒歩約${st.travel_time_minutes}分)`);
}
④ 読み物・雑学の取得(TRIVIA)
ちょっと記事に遊び心を、この場合はTRIVIAをコールする。
"advice"(アドバイス)、"zen"(偉人の名言・DummyJSON経由)、"number"を指定。
const response = await FunkApiCore.getTrivia("zen");
if (response.status === "success") {
console.log(`"${response.data.content}" — ${response.data.author}`);
// 例: "Life isn’t about getting and having..." — Kevin Kruse
}
4.詳しい関数仕様
1. 天気情報の取得 getWeather()
指定された座標の天気予報(Open-Meteo APIを利用)を取得。
【引数】
| 引数名 | 型 | 必須 | 説明/ 指定できる値 |
|---|---|---|---|
| lat | 数値 | 必須 | 緯度(例: 35.65) |
| lng | 数値 | 必須 | 経度(例: 139.54) |
| date | 文字列 | 任意 | 対象日を指定 |
dateのデフォルトは "today"。
指定可能: "today", "tomorrow", または "YYYY-MM-DD" 形式
【応答値 (data オブジェクト)】
| プロパティ名 | 型 | 意味・解釈のしかた |
|---|---|---|
| date | 文字 | 実際にデータが取得された日付(例: "2026-07-04")。 |
| weather_code | 数値 | WMO(世界気象機関)の基準に基づく天気のコード番号 |
| weather_text_ja | 文字列 | weather_code を日本語のテキストに変換した固定値。(例: "快晴", "晴れ(時に薄曇り/曇り)", "雨" など全9パターン) |
| weather_text_en | 文字列 | weather_code を英語のテキストに変換した固定値。(例: "Clear Sky", "Rain" など全9パターン) |
| temp_max | 数値 | その日の最高気温(摂氏 ℃)。(例: 28.5) |
| temp_min | 数値 | その日の最低気温(摂氏 ℃)。(例: 19.0) |
| rain_probability | 数値 | その日の最大降水確率(%)。0〜100の整数。(例: 20) |
ちなみに、weather_code(天気のコード番号)は、以下のマッピング仕様にてweather_text_ja とweather_text_en を応答。weather_codeを直接参照すれば、独自の判定基準でラベリングしたい場合に利用可能。
| weather_code | weather_text_ja | weather_text_en |
|---|---|---|
| 0 | 快晴 | Clear Sky |
| 1, 2, 3 | 晴れ(時に薄曇り/曇り) | Mainly Clear / Partly Cloudy |
| 45, 48 | 霧 | Fog |
| 51, 53, 55 | 霧雨 | Drizzle |
| 61, 63, 65 | 雨 | Rain |
| 71, 73, 75 | 雪 | Snow |
| 80, 81, 82 | にわか雨 | Rain Showers |
| 95以上 | 雷雨 | Thunderstorm |
| 上記以外 | 不明 | Unknown |
2. 祝日情報の取得 getHolidays()
日本の祝日データ(Holidays JP API)を取得。
【引数】
| 引数名 | 型 | 必須 | 説明 / 指定できる値 |
|---|---|---|---|
period |
文字列 | 必須 | 取得したい期間を指定。 ・ "next": 今日以降で最も近い次の祝日(1件のみ)・ "this_month": 今月あるすべての祝日・ "next_month": 来月あるすべての祝日 |
【応答値 (data オブジェクト)】
| プロパティ名 | 型 | 意味・解釈のしかた |
|---|---|---|
period |
文字列 | 引数で指定した検索期間がそのまま返す(エコーバック)。 |
holidays |
配列 | 該当する祝日データのリスト。該当する祝日がない月は空の配列 [] 。 |
└ date |
文字列 | 祝日の日付。(例: "2026-07-20") |
└ name |
文字列 | 日本の公式な祝日名。(例: "海の日") |
3. 最寄り駅情報の取得 getNearestStation()
指定された座標から最も近い駅情報(HeartRails Express API)を取得。
【引数】
| 引数名 | 型 | 必須 | 説明 / 指定できる値 |
|---|---|---|---|
lat |
数値 | 必須 | 現在地などの緯度(例: 35.65) |
lng |
数値 | 必須 | 現在地などの経度(例: 139.54) |
【応答値 (data オブジェクト)】
| プロパティ名 | 型 | 意味・解釈のしかた |
|---|---|---|
station_name |
文字列 | 最寄り駅の名前。「駅」という文字は含まない。(例: "新宿") |
line_name |
文字列 | その駅が属する路線名。(例: "京王線") |
distance_meters |
数値 | 指定された座標から駅までの直線距離(メートル)。 計算しやすい整数値で返す。(例: 430) |
travel_time_minutes |
数値 | 不動産表示などで使われる「徒歩1分=80m」の基準を用いて、 ライブラリ内部で distance_meters ÷ 80 を切り上げ計算した徒歩所要時間の目安(分)。(例: 6) |
4. 読み物・雑学の取得 getTrivia()
指定されたジャンルのランダムなテキストデータ(Advice Slip API、DummyJSON Quotes API、Numbers API)を取得。
【引数】
| 引数名 | 型 | 必須 | 説明 / 指定できる値 |
|---|---|---|---|
type |
文字列 | 必須 | 欲しい雑学のジャンルを指定。 ・ "advice": 日常のちょっとしたアドバイス・ "zen": 哲学者や歴史上の偉人の名言・ "number": 今日の日付にまつわる歴史の出来事(数字雑学) |
【応答値 (data オブジェクト)】
| プロパティ名 | 型 | 意味・解釈のしかた |
|---|---|---|
type |
文字列 | 引数で指定したジャンルをそのまま返す。 |
category |
文字列 | UI側でアイコンや枠の色を変えたい場合に使えるカテゴリ分類。 ・ "life": advice を指定した場合・ "philosophy": zen を指定した場合・ "date": number を指定した場合 |
content |
文字列 | 取得された名言や雑学の本文テキスト(英語)。 |
author |
文字列 | この言葉の「発言者」や「出典」です。ジャンルによって性質が変わる。 ・ "advice" の場合: 常に "Unknown"(発言者不明のアドバイス)・ "zen" の場合: 実際の発言者の名前(例: "Kevin Kruse" 等)・ "number" の場合: 常に "History"(歴史上の事実のため) |
5.ライブラリ情報
OpenAPI 3.0.0 仕様書(JSON)
"openapi": "3.0.0",
"info": {
"title": "FunkApiCore (JavaScript/ES6)",
"description": "記事埋め込みカスタム構文 [予約語] 用の独立パブリックAPIラッパーライブラリ共通仕様",
"version": "1.1.0"
},
"paths": {
"/weather": {
"get": {
"summary": "天気情報の取得 (Open-Meteo ラッパー)",
"description": "緯度・経度と日付を指定し、日英の固定文言を含む標準化された天気データを取得します。",
"parameters": [
{
"name": "lat",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "緯度"
},
{
"name": "lng",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "経度"
},
{
"name": "date",
"in": "query",
"required": false,
"schema": {
"type": "string",
"default": "today"
},
"description": "日付指定 (today, tomorrow, YYYY-MM-DD)"
}
],
"responses": {
"200": {
"description": "正常応答",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success"
},
"data": {
"type": "object",
"properties": {
"date": {
"type": "string",
"example": "2026-07-04"
},
"weather_code": {
"type": "integer",
"example": 53
},
"weather_text_en": {
"type": "string",
"example": "Drizzle"
},
"weather_text_ja": {
"type": "string",
"example": "霧雨"
},
"temp_max": {
"type": "number",
"example": 24.9
},
"temp_min": {
"type": "number",
"example": 19.0
},
"rain_probability": {
"type": "integer",
"example": 20
}
}
}
}
}
}
}
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/holiday": {
"get": {
"summary": "祝日情報の取得 (Holidays JP API ラッパー)",
"description": "指定された期間の日本の祝日データを取得します。",
"parameters": [
{
"name": "period",
"in": "query",
"required": true,
"schema": {
"type": "string",
"enum": [
"next",
"this_month",
"next_month"
]
},
"description": "取得対象期間"
}
],
"responses": {
"200": {
"description": "正常応答",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success"
},
"data": {
"type": "object",
"properties": {
"period": {
"type": "string",
"example": "next"
},
"holidays": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"example": "2026-07-20"
},
"name": {
"type": "string",
"example": "海の日"
}
}
}
}
}
}
}
}
}
}
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/nearest-station": {
"get": {
"summary": "最寄り駅情報の取得 (HeartRails Express API ラッパー)",
"description": "指定された座標から最も近い駅情報を取得します。",
"parameters": [
{
"name": "lat",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "緯度"
},
{
"name": "lng",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "経度"
}
],
"responses": {
"200": {
"description": "正常応答",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success"
},
"data": {
"type": "object",
"properties": {
"station_name": {
"type": "string",
"example": "調布"
},
"line_name": {
"type": "string",
"example": "京王線"
},
"distance_meters": {
"type": "integer",
"example": 430
},
"travel_time_minutes": {
"type": "integer",
"example": 6
}
}
}
}
}
}
}
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/trivia": {
"get": {
"summary": "読み物・雑学の取得 (Advice/DummyJSON Quotes/Numbers)",
"description": "タイプに応じたテキストデータを取得します。CORSに完全対応したエンドポイントを利用します。",
"parameters": [
{
"name": "type",
"in": "query",
"required": true,
"schema": {
"type": "string",
"enum": [
"advice",
"zen",
"number"
]
},
"description": "API種別 (zen=一般名言)"
}
],
"responses": {
"200": {
"description": "正常応答",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success"
},
"data": {
"type": "object",
"properties": {
"type": {
"type": "string",
"example": "zen"
},
"content": {
"type": "string",
"example": "Life isn’t about getting and having, it’s about giving and being."
},
"author": {
"type": "string",
"example": "Kevin Kruse"
},
"category": {
"type": "string",
"example": "philosophy"
}
}
}
}
}
}
}
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
}
},
"components": {
"responses": {
"ErrorResponse": {
"description": "エラー応答共通モデル",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "error"
},
"error": {
"type": "object",
"properties": {
"code": {
"type": "string",
"example": "TRIVIA_API_ERROR"
},
"message": {
"type": "string",
"example": "トリビア情報の取得に失敗しました。"
}
}
}
}
}
}
}
}
}
}
}