Skip to content

Commit 66320b6

Browse files
authored
Merge pull request #1 from base/ac-initial
Migrate base-docs repo
2 parents 2358b2b + 94beade commit 66320b6

File tree

1,020 files changed

+149514
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,020 files changed

+149514
-2
lines changed

.gitignore

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
.env
2+
# Node stuff
3+
node_modules
4+
yarn-debug.log*
5+
yarn-error.log*
6+
docs/dist/
7+
docs/build/
8+
vocs.config.tsx.timestamp*
9+
10+
# OS ignores
11+
.DS_Store
12+
13+
# Xcode
14+
**/ios/build/
15+
**/ios/derived_data/
16+
*.pbxuser
17+
!default.pbxuser
18+
*.mode1v3
19+
!default.mode1v3
20+
*.mode2v3
21+
!default.mode2v3
22+
*.perspectivev3
23+
!default.perspectivev3
24+
xcuserdata
25+
*.xccheckout
26+
*.moved-aside
27+
DerivedData
28+
*.hmap
29+
*.ipa
30+
*.xcuserstate
31+
*.xcworkspace
32+
Pods/
33+
34+
# Android/IntelliJ
35+
**/android/build/
36+
**/android/app/build/
37+
.idea
38+
.gradle
39+
local.properties
40+
*.iml
41+
*.hprof
42+
43+
# Nx/Builds
44+
.docusaurus
45+
.next
46+
.nx
47+
cjs/
48+
dts/
49+
esm/
50+
lib/
51+
mjs/
52+
out/
53+
*.tsbuildinfo
54+
55+
# Yarn
56+
.yarn/*
57+
!.yarn/patches
58+
!.yarn/releases
59+
!.yarn/plugins
60+
!.yarn/sdks
61+
!.yarn/versions
62+
.pnp.*
63+
# prevent people from accidentally committing a package-lock
64+
package-lock.json
65+
66+
# Env files
67+
.env.local
68+
.env.development.local
69+
.env.test.local
70+
.env.production.local
71+
72+
# GraphQL
73+
schema.graphql
74+
persisted_queries.json
75+
**/*.graphql.ts
76+
77+
# eslint
78+
.eslintcache
79+
80+
.vercel

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18

.yarnrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules

README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,27 @@
1-
# docs
2-
Documentation for building on Base
1+
This is a [Vocs](https://vocs.dev) project bootstrapped with the Vocs CLI.
2+
3+
# Creating New Docs
4+
5+
You can create a new doc by adding a `.md` or `.mdx` file in
6+
`apps/base-docs/docs/pages`.
7+
8+
The URL path for your doc will map to the file location. For instance, `bounty.mdx`
9+
is found within `chain/security`. So the URL for this link will be:
10+
`docs.base.org/chain/security/bounty`.
11+
12+
13+
# Running Docs Locally
14+
15+
Follow these steps to run Base-Docs locally:
16+
17+
1. Clone repo
18+
19+
2. Enable yarn by running `corepack enable`
20+
21+
3. Make sure you have installed all dependencies by running `yarn install` at
22+
the top-level
23+
24+
4. `yarn build`
25+
26+
4. Start development server by running `yarn dev`
27+

api/submitFeedback.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { google } from '@googleapis/sheets';
2+
import type { VercelRequest, VercelResponse } from '@vercel/node';
3+
4+
// Initialize Google Sheets client
5+
const getGoogleSheetsClient = () => {
6+
try {
7+
const credentials = JSON.parse(
8+
Buffer.from(process.env.GOOGLE_SERVICE_ACCOUNT_KEY || '', 'base64').toString(),
9+
);
10+
11+
const auth = new google.auth.GoogleAuth({
12+
credentials,
13+
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
14+
});
15+
16+
return google.sheets({ version: 'v4', auth });
17+
} catch (error) {
18+
console.error('Failed to initialize Google Sheets client:', error);
19+
throw new Error('Failed to initialize Google Sheets client');
20+
}
21+
};
22+
23+
type FeedbackPayload = {
24+
likeOrDislike: boolean;
25+
options: string[];
26+
comment: string;
27+
url: string;
28+
ipAddress: string;
29+
timestamp: number;
30+
};
31+
32+
export default async function handler(req: VercelRequest, res: VercelResponse) {
33+
if (req.method !== 'POST') {
34+
return res.status(405).json({ error: 'Method not allowed' });
35+
}
36+
37+
try {
38+
const { likeOrDislike, options, comment, url, ipAddress, timestamp } =
39+
req.body as FeedbackPayload;
40+
41+
const sheets = getGoogleSheetsClient();
42+
const spreadsheetId = process.env.GOOGLE_SHEETS_ID;
43+
44+
if (!spreadsheetId) {
45+
throw new Error('GOOGLE_SHEETS_ID environment variable is not set');
46+
}
47+
48+
// Format the row data
49+
const rowData = [
50+
new Date(timestamp).toISOString(),
51+
url,
52+
ipAddress,
53+
likeOrDislike ? 'Like' : 'Dislike',
54+
options.join(', '),
55+
comment,
56+
];
57+
58+
// Append the row to the sheet
59+
await sheets.spreadsheets.values.append({
60+
spreadsheetId,
61+
range: 'Sheet1!A:F', // Adjust range based on your sheet's structure
62+
valueInputOption: 'USER_ENTERED',
63+
requestBody: {
64+
values: [rowData],
65+
},
66+
});
67+
68+
return res.status(200).json({ success: true });
69+
} catch (error) {
70+
console.error('Error submitting feedback:', error);
71+
return res.status(500).json({ error: 'Failed to submit feedback' });
72+
}
73+
}

contexts/Theme.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
type ReactNode,
3+
createContext,
4+
useCallback,
5+
useContext,
6+
useEffect,
7+
useMemo,
8+
useState,
9+
} from 'react';
10+
11+
type Theme = 'light' | 'dark';
12+
type ThemeContextProps = {
13+
theme: Theme;
14+
toggleTheme: () => void;
15+
};
16+
17+
export const ThemeContext = createContext<ThemeContextProps>({
18+
theme: 'dark',
19+
toggleTheme: () => {},
20+
});
21+
22+
export function useTheme() {
23+
const context = useContext(ThemeContext);
24+
if (context === undefined) {
25+
throw new Error('useTheme must be used within a ThemeProvider');
26+
}
27+
return context;
28+
}
29+
30+
export default function ThemeProvider({ children }: { children: ReactNode }) {
31+
const [theme, setTheme] = useState<Theme>('dark');
32+
33+
const toggleTheme = useCallback(() => {
34+
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
35+
}, []);
36+
37+
useEffect(() => {
38+
const rootElement = document.documentElement;
39+
const observer = new MutationObserver(() => {
40+
if (rootElement.classList.contains('dark')) {
41+
setTheme('dark');
42+
} else {
43+
setTheme('light');
44+
}
45+
});
46+
47+
observer.observe(rootElement, {
48+
attributes: true,
49+
attributeFilter: ['class'],
50+
});
51+
52+
if (rootElement.classList.contains('dark')) {
53+
setTheme('dark');
54+
}
55+
56+
return () => observer.disconnect();
57+
}, []);
58+
59+
const values = useMemo(() => ({ theme, toggleTheme }), [theme, toggleTheme]);
60+
61+
return <ThemeContext.Provider value={values}>{children}</ThemeContext.Provider>;
62+
}

docs/components/App.tsx

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use client';
2+
3+
import { OnchainKitProvider } from '@coinbase/onchainkit';
4+
import '@coinbase/onchainkit/styles.css';
5+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
6+
import type { ReactNode } from 'react';
7+
import { http, WagmiProvider, createConfig } from 'wagmi';
8+
import { base, baseSepolia } from 'wagmi/chains';
9+
import { coinbaseWallet } from 'wagmi/connectors';
10+
import { useTheme } from '../contexts/Theme.tsx';
11+
import { defineChain } from 'viem';
12+
13+
const queryClient = new QueryClient();
14+
15+
export const SANDBOX_CHAIN = defineChain({
16+
id: 8453200058,
17+
name: 'Sandbox Network',
18+
nativeCurrency: {
19+
name: 'Ethereum',
20+
symbol: 'ETH',
21+
decimals: 18,
22+
},
23+
rpcUrls: {
24+
default: {
25+
http: ['https://sandbox-rpc-testnet.appchain.base.org'],
26+
},
27+
},
28+
});
29+
30+
const wagmiConfig = createConfig({
31+
chains: [base, baseSepolia, SANDBOX_CHAIN],
32+
connectors: [
33+
coinbaseWallet({
34+
appName: 'OnchainKit',
35+
}),
36+
],
37+
ssr: true,
38+
transports: {
39+
[base.id]: http(),
40+
[baseSepolia.id]: http(),
41+
[SANDBOX_CHAIN.id]: http(),
42+
},
43+
});
44+
45+
export default function App({ children }: { children: ReactNode }) {
46+
const isServer = typeof window === 'undefined';
47+
if (isServer) {
48+
return null;
49+
}
50+
51+
const viteCdpApiKey = import.meta.env.VITE_CDP_API_KEY;
52+
const viteProjectId = import.meta.env.VITE_CDP_PROJECT_ID;
53+
const { theme } = useTheme();
54+
55+
return (
56+
<WagmiProvider config={wagmiConfig}>
57+
<QueryClientProvider client={queryClient}>
58+
<OnchainKitProvider
59+
apiKey={viteCdpApiKey}
60+
chain={base} // TODO: remove
61+
projectId={viteProjectId}
62+
schemaId="0xf8b05c79f090979bf4a80270aba232dff11a10d9ca55c4f88de95317970f0de9"
63+
config={{
64+
appearance: {
65+
mode: 'auto',
66+
theme: theme,
67+
},
68+
}}
69+
>
70+
<div style={{ display: 'flex', flexDirection: 'column' }}>{children}</div>
71+
</OnchainKitProvider>
72+
</QueryClientProvider>
73+
</WagmiProvider>
74+
);
75+
}

0 commit comments

Comments
 (0)