mirror of
https://github.com/blackboxprogramming/context-bridge.git
synced 2026-03-18 04:34:02 -05:00
Add all backend files
This commit is contained in:
5
.env.example
Normal file
5
.env.example
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
STRIPE_SECRET_KEY=sk_test_your_key_here
|
||||||
|
STRIPE_WEBHOOK_SECRET=whsec_your_secret_here
|
||||||
|
GITHUB_TOKEN=ghp_your_token_here
|
||||||
|
BASE_URL=https://context-bridge-ten.vercel.app
|
||||||
|
PORT=3000
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
.vercel
|
node_modules/
|
||||||
|
.env
|
||||||
|
|||||||
11
.vercel/README.txt
Normal file
11
.vercel/README.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
> Why do I have a folder named ".vercel" in my project?
|
||||||
|
The ".vercel" folder is created when you link a directory to a Vercel project.
|
||||||
|
|
||||||
|
> What does the "project.json" file contain?
|
||||||
|
The "project.json" file contains:
|
||||||
|
- The ID of the Vercel project that you linked ("projectId")
|
||||||
|
- The ID of the user or team your Vercel project is owned by ("orgId")
|
||||||
|
|
||||||
|
> Should I commit the ".vercel" folder?
|
||||||
|
No, you should not share the ".vercel" folder with anyone.
|
||||||
|
Upon creation, it will be automatically added to your ".gitignore" file.
|
||||||
1
.vercel/project.json
Normal file
1
.vercel/project.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"projectId":"prj_KL07uJYKBqS1Wpl6qrvpCPa5b7V9","orgId":"team_TRzkNju2fGETspZKM2AkELHe","projectName":"context-bridge"}
|
||||||
17
package.json
Normal file
17
package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "context-bridge",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js",
|
||||||
|
"dev": "nodemon server.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"stripe": "^14.0.0",
|
||||||
|
"@octokit/rest": "^20.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^3.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
104
server.js
Normal file
104
server.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const Stripe = require('stripe');
|
||||||
|
const { Octokit } = require('@octokit/rest');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const stripe = Stripe(process.env.STRIPE_SECRET_KEY);
|
||||||
|
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
|
||||||
|
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.static('public'));
|
||||||
|
|
||||||
|
// Create context gist for user
|
||||||
|
app.post('/api/create-context', async (req, res) => {
|
||||||
|
const { email, name } = req.body;
|
||||||
|
|
||||||
|
const contextTemplate = `# ${name}'s Context
|
||||||
|
|
||||||
|
**Last Updated**: ${new Date().toISOString()}
|
||||||
|
**Email**: ${email}
|
||||||
|
|
||||||
|
## Current Work
|
||||||
|
|
||||||
|
[Add what you're working on]
|
||||||
|
|
||||||
|
## Active Projects
|
||||||
|
|
||||||
|
- [Project 1]
|
||||||
|
- [Project 2]
|
||||||
|
|
||||||
|
## Context for AI Assistants
|
||||||
|
|
||||||
|
When starting a conversation, I'm currently focused on: [Fill this in]
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Give this URL to any AI assistant: [This gist URL]
|
||||||
|
Update using: gh gist edit [gist-id] CURRENT_CONTEXT.md
|
||||||
|
`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const gist = await octokit.gists.create({
|
||||||
|
description: `${name}'s Context Bridge`,
|
||||||
|
public: true,
|
||||||
|
files: {
|
||||||
|
'CURRENT_CONTEXT.md': {
|
||||||
|
content: contextTemplate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
gistUrl: gist.data.html_url,
|
||||||
|
gistId: gist.data.id,
|
||||||
|
rawUrl: gist.data.files['CURRENT_CONTEXT.md'].raw_url
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create Stripe checkout
|
||||||
|
app.post('/api/create-checkout', async (req, res) => {
|
||||||
|
const { email, priceId } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const session = await stripe.checkout.sessions.create({
|
||||||
|
payment_method_types: ['card'],
|
||||||
|
line_items: [{
|
||||||
|
price: priceId,
|
||||||
|
quantity: 1,
|
||||||
|
}],
|
||||||
|
mode: 'subscription',
|
||||||
|
success_url: `${process.env.BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
|
||||||
|
cancel_url: `${process.env.BASE_URL}/`,
|
||||||
|
customer_email: email,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({ url: session.url });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Webhook handler
|
||||||
|
app.post('/api/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
|
||||||
|
const sig = req.headers['stripe-signature'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET);
|
||||||
|
|
||||||
|
if (event.type === 'checkout.session.completed') {
|
||||||
|
const session = event.data.object;
|
||||||
|
// Create gist for customer
|
||||||
|
// Send welcome email with gist URL
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ received: true });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).send(`Webhook Error: ${error.message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
||||||
85
success.html
Normal file
85
success.html
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Success - Context Bridge</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Georgia, Times, serif;
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.success-box {
|
||||||
|
border: 2px solid #0645ad;
|
||||||
|
padding: 30px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #0645ad;
|
||||||
|
border-bottom: 1px solid #a2a9b1;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
background: #eee;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
.gist-url {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #a2a9b1;
|
||||||
|
padding: 15px;
|
||||||
|
margin: 20px 0;
|
||||||
|
font-family: monospace;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="success-box">
|
||||||
|
<h1>Welcome to Context Bridge!</h1>
|
||||||
|
|
||||||
|
<p><strong>Your context file has been created.</strong></p>
|
||||||
|
|
||||||
|
<div class="gist-url" id="gist-url">Loading your context URL...</div>
|
||||||
|
|
||||||
|
<h2>How to use it</h2>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Copy the URL above</li>
|
||||||
|
<li>When starting any AI conversation, say: <code>Read [your URL] first</code></li>
|
||||||
|
<li>The AI will understand your context immediately</li>
|
||||||
|
<li>Update your context anytime: <code>gh gist edit [gist-id] CURRENT_CONTEXT.md</code></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>Next steps</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Edit your context file to add your current projects</li>
|
||||||
|
<li>Try it with Claude, ChatGPT, or GitHub Copilot</li>
|
||||||
|
<li>Update weekly (or whenever your focus changes)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p><a href="/">← Back to home</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const sessionId = urlParams.get('session_id');
|
||||||
|
|
||||||
|
if (sessionId) {
|
||||||
|
fetch(`/api/get-context?session=${sessionId}`)
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('gist-url').textContent = data.gistUrl;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
document.getElementById('gist-url').textContent = 'Check your email for your context URL';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user