Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

api-docs.tsx

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

api-docs.tsxBlame267 lines · 1 contributor
45e31d0Claude1/**
2 * API Documentation — interactive docs page.
3 */
4
5import { Hono } from "hono";
6import { Layout } from "../views/layout";
7import { softAuth } from "../middleware/auth";
8import type { AuthEnv } from "../middleware/auth";
9
10const apiDocs = new Hono<AuthEnv>();
11
12apiDocs.get("/api/docs", softAuth, (c) => {
13 const user = c.get("user");
14
15 return c.html(
16 <Layout title="API Documentation" user={user}>
17 <div style="max-width:900px">
18 <h1 style="margin-bottom:8px">gluecron API</h1>
19 <p style="color:var(--text-muted);margin-bottom:32px">
20 Complete REST API for programmatic access to repositories, issues, pull requests, and more.
21 </p>
22
23 <ApiSection
24 title="Authentication"
25 description="All API requests require authentication via a personal access token."
26 >
27 <CodeExample
28 title="Using a Bearer token"
29 code={`curl -H "Authorization: Bearer glue_your_token_here" \\
30 https://gluecron.com/api/v2/user`}
31 />
32 <p style="font-size:14px;color:var(--text-muted);margin-top:12px">
33 Create a token at <a href="/settings/tokens">/settings/tokens</a>. Tokens support scopes: <code>repo</code>, <code>user</code>, <code>admin</code>.
34 </p>
35 </ApiSection>
36
37 <ApiSection title="Rate Limits" description="Rate limits are applied per IP address.">
38 <EndpointTable
39 rows={[
40 ["API routes", "100 req/min"],
41 ["Search", "30 req/min"],
42 ["Authentication", "10 req/min"],
43 ["Git operations", "60 req/min"],
44 ]}
45 headers={["Scope", "Limit"]}
46 />
47 <p style="font-size:13px;color:var(--text-muted);margin-top:8px">
48 Rate limit info is included in response headers: <code>X-RateLimit-Limit</code>, <code>X-RateLimit-Remaining</code>, <code>X-RateLimit-Reset</code>.
49 </p>
50 </ApiSection>
51
52 <ApiSection title="Users">
53 <Endpoint method="GET" path="/api/v2/user" description="Get authenticated user" auth />
54 <Endpoint method="GET" path="/api/v2/users/:username" description="Get user by username" />
55 <Endpoint method="PATCH" path="/api/v2/user" description="Update profile (displayName, bio, avatarUrl)" auth scope="user" />
56 </ApiSection>
57
58 <ApiSection title="Repositories">
59 <Endpoint method="GET" path="/api/v2/users/:username/repos" description="List user repositories" params="sort=updated|stars|name" />
60 <Endpoint method="POST" path="/api/v2/repos" description="Create repository" auth scope="repo" />
61 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo" description="Get repository details" />
62 <Endpoint method="PATCH" path="/api/v2/repos/:owner/:repo" description="Update repository (description, visibility)" auth scope="repo" />
63 <Endpoint method="DELETE" path="/api/v2/repos/:owner/:repo" description="Delete repository" auth scope="admin" />
64 </ApiSection>
65
66 <ApiSection title="Branches">
67 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/branches" description="List all branches" />
68 </ApiSection>
69
70 <ApiSection title="Commits">
71 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/commits" description="List commits" params="ref, limit, offset" />
72 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/commits/:sha" description="Get commit with diff" />
73 </ApiSection>
74
75 <ApiSection title="File Contents">
76 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/tree/:ref" description="Get file tree at ref" params="path" />
77 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/contents/:path" description="Get file contents" params="ref" />
78 </ApiSection>
79
80 <ApiSection title="Issues">
81 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/issues" description="List issues" params="state=open|closed, limit" />
82 <Endpoint method="POST" path="/api/v2/repos/:owner/:repo/issues" description="Create issue" auth scope="repo" />
83 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/issues/:number" description="Get issue with comments" />
84 <Endpoint method="PATCH" path="/api/v2/repos/:owner/:repo/issues/:number" description="Update issue (title, body, state)" auth scope="repo" />
85 <Endpoint method="POST" path="/api/v2/repos/:owner/:repo/issues/:number/comments" description="Add comment to issue" auth scope="repo" />
86 </ApiSection>
87
88 <ApiSection title="Pull Requests">
89 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/pulls" description="List pull requests" params="state=open|closed|merged" />
90 <Endpoint method="POST" path="/api/v2/repos/:owner/:repo/pulls" description="Create pull request" auth scope="repo" />
91 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/pulls/:number" description="Get PR with comments" />
92 </ApiSection>
93
94 <ApiSection title="Stars">
95 <Endpoint method="PUT" path="/api/v2/repos/:owner/:repo/star" description="Star a repository" auth />
96 <Endpoint method="DELETE" path="/api/v2/repos/:owner/:repo/star" description="Unstar a repository" auth />
97 </ApiSection>
98
99 <ApiSection title="Labels">
100 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/labels" description="List labels" />
101 <Endpoint method="POST" path="/api/v2/repos/:owner/:repo/labels" description="Create label" auth scope="repo" />
102 </ApiSection>
103
104 <ApiSection title="Search">
105 <Endpoint method="GET" path="/api/v2/search/repos" description="Search repositories" params="q (required), sort, limit" />
106 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/search/code" description="Search code in repository" params="q (required)" />
107 </ApiSection>
108
109 <ApiSection title="Topics">
110 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/topics" description="Get repository topics" />
111 <Endpoint method="PUT" path="/api/v2/repos/:owner/:repo/topics" description="Set repository topics" auth scope="repo" />
112 </ApiSection>
113
114 <ApiSection title="Webhooks">
115 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/webhooks" description="List webhooks" auth scope="repo" />
116 <Endpoint method="POST" path="/api/v2/repos/:owner/:repo/webhooks" description="Create webhook" auth scope="admin" />
117 </ApiSection>
118
119 <ApiSection title="Activity Feed">
120 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/activity" description="Get activity feed" params="limit" />
121 </ApiSection>
122
123 <ApiSection title="Status Checks (CI Integration)">
124 <Endpoint method="POST" path="/api/v2/repos/:owner/:repo/statuses/:sha" description="Create status check" auth scope="repo" />
125 <Endpoint method="GET" path="/api/v2/repos/:owner/:repo/statuses/:sha" description="Get status checks for commit" />
126 <CodeExample
127 title="Report CI status"
128 code={`curl -X POST -H "Authorization: Bearer glue_xxx" \\
129 -H "Content-Type: application/json" \\
130 -d '{"context":"ci/build","state":"success","targetUrl":"https://ci.example.com/build/123"}' \\
131 https://gluecron.com/api/v2/repos/user/repo/statuses/abc123`}
132 />
133 </ApiSection>
134
135 <div style="text-align:center;padding:40px 0;color:var(--text-muted)">
136 <p>API index: <code>GET /api/v2</code> returns machine-readable endpoint listing</p>
137 <p style="margin-top:8px;font-size:13px">Press <kbd class="kbd">?</kbd> for keyboard shortcuts</p>
138 </div>
139 </div>
140 </Layout>
141 );
142});
143
144// ─── Documentation Components ────────────────────────────────────────────
145
146const ApiSection = ({
147 title,
148 description,
149 children,
150}: {
151 title: string;
152 description?: string;
153 children: any;
154}) => (
155 <div style="margin-bottom:32px">
156 <h2 style="font-size:20px;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid var(--border)">
157 {title}
158 </h2>
159 {description && (
160 <p style="color:var(--text-muted);font-size:14px;margin-bottom:16px">{description}</p>
161 )}
162 {children}
163 </div>
164);
165
166const Endpoint = ({
167 method,
168 path,
169 description,
170 params,
171 auth,
172 scope,
173}: {
174 method: string;
175 path: string;
176 description: string;
177 params?: string;
178 auth?: boolean;
179 scope?: string;
180}) => {
181 const methodColor =
182 method === "GET" ? "var(--green)" :
183 method === "POST" ? "var(--accent)" :
184 method === "PUT" || method === "PATCH" ? "var(--yellow)" :
185 method === "DELETE" ? "var(--red)" : "var(--text)";
186
187 return (
188 <div style="padding:10px 0;border-bottom:1px solid var(--border);display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap">
189 <span style={`font-family:var(--font-mono);font-size:12px;font-weight:700;color:${methodColor};min-width:60px`}>
190 {method}
191 </span>
192 <code style="font-size:13px;color:var(--text-link);flex:1;min-width:200px">{path}</code>
193 <span style="font-size:13px;color:var(--text-muted);flex:2;min-width:200px">
194 {description}
195 {params && (
196 <span style="display:block;font-size:12px;margin-top:2px">
197 Params: <code>{params}</code>
198 </span>
199 )}
200 </span>
201 <span style="display:flex;gap:4px;flex-shrink:0">
202 {auth && (
203 <span style="font-size:11px;padding:2px 6px;border-radius:3px;background:rgba(31,111,235,0.15);color:var(--accent)">
204 AUTH
205 </span>
206 )}
207 {scope && (
208 <span style="font-size:11px;padding:2px 6px;border-radius:3px;background:rgba(63,185,80,0.15);color:var(--green)">
209 {scope}
210 </span>
211 )}
212 </span>
213 </div>
214 );
215};
216
217const CodeExample = ({ title, code }: { title: string; code: string }) => (
218 <div style="margin:12px 0">
219 {title && (
220 <div style="font-size:13px;color:var(--text-muted);margin-bottom:4px">{title}</div>
221 )}
222 <div style="position:relative">
223 <pre style="background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius);padding:12px 16px;font-family:var(--font-mono);font-size:13px;overflow-x:auto;line-height:1.6">
224 {code}
225 </pre>
226 <button
227 type="button"
228 class="btn btn-sm"
229 data-clipboard={code}
230 style="position:absolute;top:8px;right:8px;font-size:11px"
231 >
232 Copy
233 </button>
234 </div>
235 </div>
236);
237
238const EndpointTable = ({
239 headers,
240 rows,
241}: {
242 headers: string[];
243 rows: string[][];
244}) => (
245 <table class="file-table" style="margin:8px 0">
246 <thead>
247 <tr>
248 {headers.map((h) => (
249 <th style="padding:8px 16px;text-align:left;font-size:13px;color:var(--text-muted);border-bottom:1px solid var(--border)">
250 {h}
251 </th>
252 ))}
253 </tr>
254 </thead>
255 <tbody>
256 {rows.map((row) => (
257 <tr>
258 {row.map((cell) => (
259 <td style="padding:8px 16px;font-size:14px">{cell}</td>
260 ))}
261 </tr>
262 ))}
263 </tbody>
264 </table>
265);
266
267export default apiDocs;