-
Notifications
You must be signed in to change notification settings - Fork 54
Jm/documentation feedback form #713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
JonathanMatthey
wants to merge
16
commits into
main
Choose a base branch
from
jm/documentation-feedback-form
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
81ee6f7
feat: add footer feedback that connects to githb issues
1371694
feat: add language support - remove alert
a73a778
fix: adjust with SSR
5b8f3cf
fix: add netlify adapter
9eca0fc
fix: move feedback readme to docs
efda669
fix: read language from url
0435790
fix: hide feedback on splash and 404 pages
a7d3782
fix: gitignore netlify
d7342bd
hide feedbackwidget from 404 page
8ef1178
fix: remove unused ui translations
7f9299f
fix: use netlify env variables for github token
cac8e49
new repo name
e64c7c2
remove unused code
4d7e700
add lock file
c947ee2
update package dev dep
9a41a22
lock file;
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,3 +19,6 @@ pnpm-debug.log* | |
|
|
||
| # macOS-specific files | ||
| .DS_Store | ||
|
|
||
| # Local Netlify folder | ||
| .netlify | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # Feedback Widget - GitHub Issues Integration | ||
|
|
||
| The feedback widget is **fully integrated with GitHub Issues** via a Netlify Function. When users submit feedback, it automatically creates an issue in your repository. | ||
|
|
||
| ## 🚀 Quick Setup | ||
|
|
||
| ### Step 1: Create a GitHub Personal Access Token | ||
|
|
||
| 1. Go to: https://github.com/settings/tokens/new | ||
| 2. Give it a name: "Interledger Docs Feedback" | ||
| 3. Select expiration (recommend: 90 days or No expiration) | ||
| 4. Select scopes: **`public_repo`** (for public repositories) | ||
| 5. Click "Generate token" | ||
| 6. **Copy the token** (you won't see it again!) | ||
|
|
||
| ### Step 2: Add Token to Netlify Environment Variables | ||
|
|
||
| #### For Local Development | ||
|
|
||
| Create a `.env` file in the `/docs` directory: | ||
|
|
||
| ```env | ||
| GITHUB_TOKEN=ghp_your_actual_token_here | ||
| ``` | ||
|
|
||
| ⚠️ **Important:** Make sure `.env` is in your `.gitignore` (it should be by default) | ||
|
|
||
| #### For Production (Netlify) | ||
|
|
||
| 1. Go to your site in the Netlify dashboard | ||
| 2. Navigate to **Site settings > Environment variables** | ||
| 3. Click **Add a variable** | ||
| 4. Set: | ||
| - **Key:** `GITHUB_TOKEN` | ||
| - **Value:** Your GitHub personal access token | ||
| - **Scopes:** All scopes (or specific deploy contexts if needed) | ||
| 5. Click **Create variable** | ||
| 6. Trigger a new deploy for the changes to take effect | ||
|
|
||
| ## 🏗️ Architecture | ||
|
|
||
| The feedback system uses a **Netlify Function** (serverless) to securely handle GitHub API authentication: | ||
|
|
||
| ``` | ||
| User clicks feedback → FeedbackWidget.astro → /.netlify/functions/feedback → GitHub API | ||
| ``` | ||
|
|
||
| **Files:** | ||
| - `/docs/netlify/functions/feedback.ts` - Netlify Function that creates GitHub issues | ||
| - `/docs/src/components/FeedbackWidget.astro` - Frontend widget component | ||
| - `/docs/src/components/Footer.astro` - Conditionally displays the widget | ||
| - `/docs/netlify.toml` - Netlify configuration | ||
|
|
||
| ## 🧪 Testing Locally | ||
|
|
||
| To test the feedback widget with Netlify Functions locally: | ||
|
|
||
| ```bash | ||
| # Install Netlify CLI if you haven't already | ||
| npm install -g netlify-cli | ||
|
|
||
| # Run the dev server with Netlify Functions | ||
| cd docs | ||
| netlify dev | ||
| ``` | ||
|
|
||
| This will start the Astro dev server and make the Netlify Functions available at `/.netlify/functions/feedback`. | ||
|
|
||
| ## 📝 How It Works | ||
|
|
||
| 1. User clicks "Yes" or "No" on a documentation page | ||
| 2. Widget shows a textarea for optional feedback | ||
| 3. On submit, JavaScript sends POST request to `/.netlify/functions/feedback` | ||
| 4. Netlify Function authenticates with GitHub using `GITHUB_TOKEN` env var | ||
| 5. Function creates an issue in `interledger/open-payments-docs-feedback` repository | ||
| 6. Issue is automatically labeled with `feedback`, `docs`, and sentiment label | ||
| 7. Widget shows success message | ||
|
|
||
| ## 🔒 Security | ||
|
|
||
| - ✅ GitHub token is stored securely in Netlify environment variables | ||
| - ✅ Token is never exposed to the client/browser | ||
| - ✅ Function runs server-side only | ||
| - ✅ CORS is handled automatically by Netlify | ||
|
|
||
| ## 🎯 Fallback Behavior | ||
|
|
||
| If the GitHub token is not configured or the API fails, the widget will: | ||
| 1. Open a pre-filled GitHub issue creation page in a new tab | ||
| 2. User can manually submit the feedback | ||
| 3. This ensures feedback is never lost |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| [build] | ||
| command = "pnpm build" | ||
| publish = "dist" | ||
|
|
||
| [functions] | ||
| directory = "netlify/functions" | ||
| node_bundler = "esbuild" | ||
|
|
||
| # Environment variables (set these in Netlify UI) | ||
| # GITHUB_TOKEN = "your-github-personal-access-token" | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| import type { Handler, HandlerEvent, HandlerContext } from '@netlify/functions'; | ||
|
|
||
| const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => { | ||
| // Only allow POST requests | ||
| if (event.httpMethod !== 'POST') { | ||
| return { | ||
| statusCode: 405, | ||
| body: JSON.stringify({ error: 'Method not allowed' }) | ||
| }; | ||
| } | ||
|
|
||
| try { | ||
| const data = JSON.parse(event.body || '{}'); | ||
| const { type, page, message } = data; | ||
|
|
||
| // Get GitHub token from environment variable | ||
| const GITHUB_TOKEN = process.env.GITHUB_TOKEN; | ||
| const GITHUB_REPO = 'interledger/open-payments-docs-feedback'; | ||
|
|
||
| if (!GITHUB_TOKEN) { | ||
| console.error('GITHUB_TOKEN not configured'); | ||
| return { | ||
| statusCode: 500, | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ | ||
| success: false, | ||
| error: 'GitHub token not configured' | ||
| }) | ||
| }; | ||
| } | ||
|
|
||
| // Create issue title and body | ||
| const emoji = type === 'yes' ? '👍' : '👎'; | ||
| const sentiment = type === 'yes' ? 'Positive' : 'Negative'; | ||
| const issueTitle = `[Feedback] ${emoji} ${page}`; | ||
|
|
||
| const issueBody = `**Page:** ${page} | ||
| **Feedback Type:** ${sentiment} ${emoji} | ||
| **User Message:** | ||
|
|
||
| ${message || '_No additional feedback provided_'} | ||
|
|
||
| --- | ||
| _Submitted via feedback widget on ${new Date().toISOString()}_`; | ||
|
|
||
| // Create GitHub issue | ||
| const response = await fetch( | ||
| `https://api.github.com/repos/${GITHUB_REPO}/issues`, | ||
| { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Authorization': `token ${GITHUB_TOKEN}`, | ||
| 'Accept': 'application/vnd.github.v3+json', | ||
| 'Content-Type': 'application/json', | ||
| 'User-Agent': 'Interledger-Docs-Feedback-Widget' | ||
| }, | ||
| body: JSON.stringify({ | ||
| title: issueTitle, | ||
| body: issueBody, | ||
| labels: [ | ||
| 'feedback', | ||
| 'docs', | ||
| type === 'yes' ? 'feedback-positive' : 'feedback-negative' | ||
| ] | ||
| }) | ||
| } | ||
| ); | ||
|
|
||
| if (!response.ok) { | ||
| const errorData = await response.text(); | ||
| console.error('GitHub API error:', errorData); | ||
| throw new Error(`GitHub API returned ${response.status}`); | ||
| } | ||
|
|
||
| const issue = await response.json(); | ||
|
|
||
| return { | ||
| statusCode: 200, | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ | ||
| success: true, | ||
| issueUrl: issue.html_url, | ||
| issueNumber: issue.number | ||
| }) | ||
| }; | ||
|
|
||
| } catch (error) { | ||
| console.error('Error creating GitHub issue:', error); | ||
| return { | ||
| statusCode: 500, | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ | ||
| success: false, | ||
| error: error instanceof Error ? error.message : 'Unknown error' | ||
| }) | ||
| }; | ||
| } | ||
| }; | ||
|
|
||
| export { handler }; | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.