Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,061 changes: 1,061 additions & 0 deletions docs/connected-apps.mdx

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ const config = {
position: "left",
label: "Updates",
},
{
type: "doc",
docId: "connected-apps",
position: "left",
label: "Connected Apps",
},

{
type: "docSidebar",
Expand Down Expand Up @@ -233,7 +239,6 @@ const config = {
],
},
{
sidebarId: "APIsSidebar",
type: "dropdown",
label: "APIs",
position: "left",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"deploy:pages": "yarn run build && wrangler pages deploy build",
"docusaurus": "npx docusaurus",
"llms:sync": "node scripts/sync-static-llms-txt.js",
"test": "node --test \"tests/**/*.test.cjs\"",
"test": "node scripts/run-tests.cjs",
"audit:search-console:local": "node scripts/audit-search-console-coverage.js --mode=local",
"audit:search-console:live": "node scripts/audit-search-console-coverage.js --mode=live",
"postbuild:seo": "node scripts/postbuild-seo.js",
Expand Down
2 changes: 2 additions & 0 deletions plugins/llms-txt-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const SECTION_ORDER = [

const URL_PRIORITY = [
`${BASE_URL}/docs/developer-journey/`,
`${BASE_URL}/docs/connected-apps/`,
`${BASE_URL}/docs/api-reference/`,
`${BASE_URL}/docs/tutorials/oidc/starter-with-npx/`,
`${BASE_URL}/docs/sdk/javascript/`,
Expand Down Expand Up @@ -104,6 +105,7 @@ const OPENAPI_HEADER = [
'- [QF_REVIEW_EXISTING_INTEGRATION_PROMPT_V1](https://api-docs.quran.foundation/agent-prompts/qf-review-existing-integration.md): Copyable prompt for auditing an existing Quran Foundation integration',
'- [Agent prompt registry](https://api-docs.quran.foundation/.well-known/agent-prompts/index.json): Machine-readable prompt catalog',
'- [Developer Journey](https://api-docs.quran.foundation/docs/developer-journey/): Choose the right starting point by app shape',
'- [Connected Apps](https://api-docs.quran.foundation/docs/connected-apps/): Partner guide for app discovery, listing review, visibility, and responsible integration',
'- [API Reference](https://api-docs.quran.foundation/docs/api-reference/): Choose between Content, Search, User APIs, OAuth2, and pre-live endpoint references',
'- [Starter With NPX](https://api-docs.quran.foundation/docs/tutorials/oidc/starter-with-npx/): One-command Next.js app scaffold',
'- [JavaScript SDK](https://api-docs.quran.foundation/docs/sdk/javascript/): Runtime-split SDK guidance for public and server code',
Expand Down
36 changes: 36 additions & 0 deletions scripts/run-tests.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const { spawnSync } = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');

const repoRoot = path.join(__dirname, '..');
const testsDir = path.join(repoRoot, 'tests');

const collectTestFiles = (dir) => {
const entries = fs.readdirSync(dir, { withFileTypes: true });
const files = [];

for (const entry of entries) {
const entryPath = path.join(dir, entry.name);

if (entry.isDirectory()) {
files.push(...collectTestFiles(entryPath));
} else if (/\.test\.cjs$/u.test(entry.name)) {
files.push(entryPath);
}
}

return files;
};

const testFiles = collectTestFiles(testsDir).sort();

if (testFiles.length === 0) {
console.error('No test files found under tests/**/*.test.cjs');
process.exit(1);
}

const result = spawnSync(process.execPath, ['--test', ...testFiles], {
stdio: 'inherit',
});
Comment thread
basit3407 marked this conversation as resolved.

process.exit(result.status ?? 1);
Comment thread
basit3407 marked this conversation as resolved.
5 changes: 5 additions & 0 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,11 @@ const makeSharedDocsSidebar = (apiFamilies) => [
id: "developer-journey",
label: "Developer Journey",
},
{
type: "doc",
id: "connected-apps",
label: "Connected Apps",
},
{
type: "doc",
id: "ai-agents/index",
Expand Down
268 changes: 268 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,271 @@ a.navbar__item--request-access:hover {
transform: translateY(-1px);
box-shadow: var(--qf-shadow-md);
}

/* Connected Apps guide */
.connectedAppsDoc {
--connected-apps-border: var(--qf-border-card);
--connected-apps-soft: rgba(62, 193, 201, 0.08);
--connected-apps-soft-strong: rgba(62, 193, 201, 0.14);
}
Comment thread
Copilot marked this conversation as resolved.

.connectedAppsVersion {
display: flex;
flex-wrap: wrap;
gap: 0.35rem 0.75rem;
margin: -0.4rem 0 1rem;
color: var(--qf-text-muted);
font-size: 0.82rem;
}

.connectedAppsHero {
margin: 0 0 1.25rem;
padding: 1.5rem;
border: 1px solid var(--connected-apps-border, var(--qf-border-card));
border-radius: var(--qf-radius-xl);
background:
linear-gradient(135deg, var(--connected-apps-soft, rgba(62, 193, 201, 0.08)), transparent 68%),
var(--ifm-background-surface-color);
box-shadow: var(--qf-shadow-sm);
}

.connectedAppsEyebrow,
.connectedAppsCardKicker {
margin: 0 0 0.35rem;
color: var(--ifm-color-primary-dark);
font-size: 0.75rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}

.connectedAppsHero h2 {
margin: 0;
color: var(--ifm-heading-color);
font-size: clamp(1.75rem, 4vw, 2.55rem);
line-height: 1.12;
}

.connectedAppsHero p:not(.connectedAppsEyebrow) {
max-width: 46rem;
margin: 0.85rem 0 0;
color: var(--ifm-color-emphasis-800);
font-size: 1rem;
line-height: 1.65;
}

.connectedAppsHeroActions {
display: flex;
flex-wrap: wrap;
gap: 0.65rem;
margin-top: 1rem;
}

.connectedAppsPrimaryLink,
.connectedAppsSecondaryLink {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 2.35rem;
padding: 0.5rem 0.9rem;
border-radius: var(--ifm-global-radius);
font-size: 0.88rem;
font-weight: 800;
text-decoration: none;
}

.connectedAppsPrimaryLink {
background: var(--ifm-color-primary);
color: #ffffff;
}

.connectedAppsPrimaryLink:hover {
background: var(--ifm-color-primary-dark);
color: #ffffff;
text-decoration: none;
}

.connectedAppsSecondaryLink {
border: 1px solid var(--connected-apps-border, var(--qf-border-card));
color: var(--ifm-color-primary-dark);
background: var(--ifm-background-color);
}

.connectedAppsSecondaryLink:hover {
color: var(--ifm-color-primary-darker);
text-decoration: none;
}

.connectedAppsPillRow {
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
margin-top: 1rem;
}

.connectedAppsPill {
display: inline-flex;
align-items: center;
border: 1px solid var(--connected-apps-border, var(--qf-border-card));
border-radius: 999px;
padding: 0.28rem 0.6rem;
color: var(--ifm-color-primary-dark);
background: var(--ifm-background-color);
font-size: 0.76rem;
font-weight: 800;
}

.connectedAppsCallout {
margin: 1rem 0 1.25rem;
padding: 0.9rem 1rem;
border: 1px solid rgba(62, 193, 201, 0.32);
border-left: 4px solid var(--ifm-color-primary);
border-radius: 0 var(--qf-radius-lg) var(--qf-radius-lg) 0;
background: var(--connected-apps-soft, rgba(62, 193, 201, 0.08));
color: var(--ifm-color-emphasis-800);
line-height: 1.55;
}

.connectedAppsGrid {
display: grid;
gap: 0.85rem;
margin: 1rem 0 1.35rem;
}

.connectedAppsGridTwo {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.connectedAppsGridThree {
grid-template-columns: repeat(3, minmax(0, 1fr));
}

.connectedAppsCard {
min-width: 0;
padding: 1rem;
border: 1px solid var(--connected-apps-border, var(--qf-border-card));
border-radius: var(--qf-radius-lg);
background: var(--ifm-background-surface-color);
box-shadow: var(--qf-shadow-sm);
}

.connectedAppsCard h3 {
margin: 0;
color: var(--ifm-heading-color);
font-size: 1.05rem;
line-height: 1.3;
}

.connectedAppsCard p,
.connectedAppsCard li {
color: var(--ifm-color-emphasis-800);
font-size: 0.9rem;
line-height: 1.55;
}

.connectedAppsCard p {
margin: 0.5rem 0 0;
}

.connectedAppsCard > a {
display: inline-flex;
margin-top: 0.7rem;
font-size: 0.88rem;
font-weight: 800;
}

.connectedAppsCard p a,
.connectedAppsCard li a {
display: inline;
margin-top: 0;
font-size: inherit;
font-weight: 800;
}

.connectedAppsNumber {
display: grid;
width: 1.65rem;
height: 1.65rem;
margin-bottom: 0.65rem;
place-items: center;
border-radius: 8px;
color: var(--ifm-color-primary-dark);
background: var(--connected-apps-soft-strong, rgba(62, 193, 201, 0.14));
font-size: 0.76rem;
font-weight: 800;
}

.connectedAppsChecklist {
margin: 0.65rem 0 0;
padding-left: 1.15rem;
}

.connectedAppsChecklist li + li {
margin-top: 0.35rem;
}

.connectedAppsTableWrap {
margin: 1rem 0 1.5rem;
overflow-x: auto;
border: 1px solid var(--connected-apps-border, var(--qf-border-card));
border-radius: var(--qf-radius-lg);
background: var(--ifm-background-surface-color);
}

.connectedAppsTable {
width: 100%;
min-width: 760px;
border-collapse: collapse;
font-size: 0.88rem;
}

.connectedAppsTable th,
.connectedAppsTable td {
padding: 0.8rem;
border-bottom: 1px solid var(--connected-apps-border, var(--qf-border-card));
text-align: left;
vertical-align: top;
}

.connectedAppsTable th {
color: var(--qf-text-muted);
background: var(--ifm-color-emphasis-100);
font-size: 0.73rem;
font-weight: 800;
letter-spacing: 0.06em;
text-transform: uppercase;
}

.connectedAppsTable tr:last-child td {
border-bottom: 0;
}

[data-theme='dark'] .connectedAppsEyebrow,
[data-theme='dark'] .connectedAppsCardKicker,
[data-theme='dark'] .connectedAppsPill,
[data-theme='dark'] .connectedAppsSecondaryLink,
[data-theme='dark'] .connectedAppsNumber {
color: var(--ifm-color-primary-light);
}

@media screen and (max-width: 996px) {
.connectedAppsGridThree {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media screen and (max-width: 760px) {
.connectedAppsHero {
padding: 1.1rem;
}

.connectedAppsGridTwo,
.connectedAppsGridThree {
grid-template-columns: 1fr;
}

.connectedAppsPrimaryLink,
.connectedAppsSecondaryLink {
width: 100%;
}
}
7 changes: 7 additions & 0 deletions static/.well-known/mcp/server-card.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@
"description": "Starting-point guide for choosing between the starter app, Content APIs, User APIs, OAuth2, and API reference docs.",
"mimeType": "text/html"
},
{
"name": "connected_apps",
"title": "Connected Apps",
"uri": "https://api-docs.quran.foundation/docs/connected-apps/",
"description": "Partner guide for Quran Foundation app discovery, listing review, visibility, and responsible integration.",
"mimeType": "text/html"
},
{
"name": "api_reference",
"title": "API Reference",
Expand Down
Loading