-
Notifications
You must be signed in to change notification settings - Fork 913
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add open-ai example * update router references * Update preview.yml
- Loading branch information
Showing
10 changed files
with
291 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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 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 |
---|---|---|
|
@@ -26,6 +26,10 @@ with-nextjs/out | |
# Websockets | ||
*/backend/.env | ||
|
||
# local env files | ||
*/.env*.local | ||
|
||
|
||
.DS_Store | ||
report.html | ||
|
||
|
This file contains 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,2 @@ | ||
# You can get your key from https://platform.openai.com/api-keys | ||
OPENAI_API_KEY=YOUR_KEY |
This file contains 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,40 @@ | ||
# Open AI Example | ||
|
||
Use [Expo API Routes](https://docs.expo.dev/router/reference/api-routes/) to securely interact with the [OpenAI API](https://platform.openai.com/docs/introduction). | ||
|
||
## Structure | ||
|
||
- `app/api/generate+api.ts`: [Expo API Route](https://docs.expo.dev/router/reference/api-routes/) that interacts with the [OpenAI API](https://platform.openai.com/docs/introduction). | ||
- `app/index.tsx`: Screen that uses the API Route to prompt the user and display results. | ||
- `.env`: The environment variable file with references to your secret [OpenAI API key](https://platform.openai.com/api-keys). | ||
|
||
## 🚀 How to use | ||
|
||
```sh | ||
npx create-expo-app -e with-openai | ||
``` | ||
|
||
Replace `OPENAI_API_KEY=YOUR_KEY` in `.env` with your [OpenAI API key](https://platform.openai.com/api-keys). | ||
|
||
Replace `origin` in the `app.json` with the URL to your [production API Routes](https://docs.expo.dev/router/reference/api-routes/#deployment) domain. This enables relative fetch requests. | ||
|
||
```json | ||
{ | ||
"expo": { | ||
"extra": { | ||
"api": { | ||
"origin": "https://my-expo-website.com" | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Ensure you upload your environment variables to wherever you host the web app and API Routes. | ||
|
||
## 📝 Notes | ||
|
||
- [Expo Router: API Routes](https://docs.expo.dev/router/reference/api-routes/) | ||
- [Expo Router: Server Deployment](https://docs.expo.dev/router/reference/api-routes/#deployment) | ||
- [Expo Router Docs](https://docs.expo.dev/router/introduction/) | ||
- [Open AI Docs](https://platform.openai.com/docs/introduction) |
This file contains 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,17 @@ | ||
{ | ||
"expo": { | ||
"scheme": "acme", | ||
"web": { | ||
"output": "server", | ||
"bundler": "metro" | ||
}, | ||
"plugins": [ | ||
[ | ||
"expo-router", | ||
{ | ||
"origin": "https://n" | ||
} | ||
] | ||
] | ||
} | ||
} |
This file contains 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,72 @@ | ||
import { ExpoRequest, ExpoResponse } from "expo-router/server"; | ||
|
||
const ENDPOINT = "https://api.openai.com/v1/chat/completions"; | ||
|
||
export async function POST(req: ExpoRequest): Promise<ExpoResponse> { | ||
const { prompt } = await req.json(); | ||
console.log("prompt:", prompt); | ||
const content = `Generate 2 app startup ideas that are optimal for Expo Router where you can develop a native app and website simultaneously with automatic universal links and API routes. Format the response as a JSON array with objects containing a "name" and "description" field, both of type string, with no additional explanation above or below the results. Base it on this context: ${prompt}.`; | ||
|
||
// const json = FIXTURES.success; | ||
|
||
// calling the OpenAI API endpoint | ||
const json = await fetch(ENDPOINT, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, | ||
}, | ||
body: JSON.stringify({ | ||
model: "gpt-3.5-turbo", | ||
messages: [{ role: "user", content }], | ||
temperature: 1.2, | ||
max_tokens: 1100, // You can customize this | ||
}), | ||
}).then((res) => res.json()); | ||
|
||
// For creating new fixtures. | ||
// console.log("json:", JSON.stringify(json, null, 2)); | ||
|
||
if (json.choices?.[0]) { | ||
// Assuming the LLM always returns the data in the expected format. | ||
const llmResponse = JSON.parse(json.choices[0].message.content.trim()); | ||
return ExpoResponse.json(llmResponse); | ||
} | ||
|
||
if (json.error) { | ||
return new ExpoResponse(json.error.message, { status: 400 }); | ||
} | ||
|
||
return ExpoResponse.json(json); | ||
} | ||
|
||
const FIXTURES = { | ||
success: { | ||
id: "chatcmpl-xxx", | ||
object: "chat.completion", | ||
created: 1702423839, | ||
model: "gpt-3.5-turbo-0613", | ||
choices: [ | ||
{ | ||
index: 0, | ||
message: { | ||
role: "assistant", | ||
content: | ||
'[\n {"name": "BeatsTime", "description": "BeatsTime is a social music platform where users can discover and share their favorite tracks with friends. The app allows users to create personalized playlists, follow their favorite DJs, and explore trending music genres."},\n {"name": "SyncSound", "description": "SyncSound is a collaborative music app that enables users to create synchronized playlists and listen to music together in real-time. Users can invite friends to join their session, vote on the next track, and chat with each other while enjoying a synchronized music experience."}\n]', | ||
}, | ||
finish_reason: "stop", | ||
}, | ||
], | ||
usage: { prompt_tokens: 81, completion_tokens: 118, total_tokens: 199 }, | ||
system_fingerprint: null, | ||
}, | ||
error: { | ||
error: { | ||
message: | ||
"You exceeded your current quota, please check your plan and billing details.", | ||
type: "insufficient_quota", | ||
param: null, | ||
code: "insufficient_quota", | ||
}, | ||
}, | ||
}; |
This file contains 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,122 @@ | ||
import React from "react"; | ||
import { Text, View, Button, StyleSheet, TextInput } from "react-native"; | ||
|
||
interface State { | ||
loading: boolean; | ||
content: { name: string; description: string }[] | null; | ||
} | ||
|
||
export default function Page() { | ||
const [{ loading, content }, setState] = React.useReducer( | ||
(state: State, newState: Partial<State>) => ({ ...state, ...newState }), | ||
{ | ||
loading: false, | ||
content: null, | ||
} | ||
); | ||
|
||
const [input, setInput] = React.useState(""); | ||
|
||
const generateContent = async () => { | ||
setState({ | ||
content: null, | ||
loading: true, | ||
}); | ||
|
||
try { | ||
const response = await fetch("/api/generate", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
prompt: input, | ||
}), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(response.statusText); | ||
} | ||
|
||
const content = await response.json(); | ||
setState({ | ||
content, | ||
loading: false, | ||
}); | ||
} catch (error) { | ||
setState({ | ||
content: null, | ||
loading: false, | ||
}); | ||
throw error; | ||
} | ||
}; | ||
|
||
return ( | ||
<View style={styles.container}> | ||
<View style={styles.main}> | ||
<Text style={styles.title}>Expo App Idea Generator</Text> | ||
|
||
<TextInput | ||
value={input} | ||
style={{ | ||
minHeight: 120, | ||
borderWidth: 1, | ||
padding: 8, | ||
}} | ||
onChange={(e) => setInput(e.nativeEvent.text)} | ||
rows={4} | ||
placeholderTextColor={"#9CA3AF"} | ||
placeholder="e.g. AI app idea generator." | ||
/> | ||
|
||
<Button | ||
disabled={loading} | ||
onPress={() => generateContent()} | ||
title={loading ? "Loading..." : "Generate"} | ||
/> | ||
|
||
{content != null && ( | ||
<> | ||
<Text style={styles.subtitle}>Generated Ideas:</Text> | ||
{content.map(({ name, description }, index) => ( | ||
<View key={String(index)}> | ||
<Text style={styles.title}>{name}</Text> | ||
<Text>{description}</Text> | ||
</View> | ||
))} | ||
</> | ||
)} | ||
</View> | ||
</View> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
alignItems: "stretch", | ||
justifyContent: "center", | ||
marginHorizontal: "auto", | ||
}, | ||
main: { | ||
flex: 1, | ||
gap: 8, | ||
justifyContent: "center", | ||
alignItems: "stretch", | ||
maxWidth: 640, | ||
paddingHorizontal: 24, | ||
}, | ||
title: { | ||
fontSize: 20, | ||
fontWeight: "bold", | ||
}, | ||
subtitle: { | ||
fontSize: 24, | ||
}, | ||
separator: { | ||
marginVertical: 30, | ||
height: 1, | ||
width: "80%", | ||
}, | ||
}); |
This file contains 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,27 @@ | ||
{ | ||
"name": "with-openai", | ||
"version": "1.0.0", | ||
"main": "expo-router/entry", | ||
"scripts": { | ||
"start": "expo start" | ||
}, | ||
"dependencies": { | ||
"expo": "^50.0.0-preview.1", | ||
"expo-constants": "~15.4.0", | ||
"expo-linking": "~6.2.1", | ||
"expo-router": "~3.3.0", | ||
"expo-splash-screen": "~0.26.0", | ||
"expo-status-bar": "~1.11.0", | ||
"react": "18.2.0", | ||
"react-dom": "18.2.0", | ||
"react-native": "0.73.0", | ||
"react-native-safe-area-context": "4.7.4", | ||
"react-native-screens": "~3.27.0", | ||
"react-native-web": "~0.19.6" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "~18.2.14", | ||
"typescript": "^5.3.0", | ||
"@babel/core": "^7.20.0" | ||
} | ||
} |
This file contains 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,4 @@ | ||
{ | ||
"compilerOptions": {}, | ||
"extends": "expo/tsconfig.base" | ||
} |
This file contains 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