Initial commit
14
.env.example
Normal file
@ -0,0 +1,14 @@
|
||||
# Since the ".env" file is gitignored, you can use the ".env.example" file to
|
||||
# build a new ".env" file when you clone the repo. Keep this file up-to-date
|
||||
# when you add new variables to `.env`.
|
||||
|
||||
# This file will be committed to version control, so make sure not to have any
|
||||
# secrets in it. If you are cloning this repo, create a copy of this file named
|
||||
# ".env" and populate it with your secrets.
|
||||
|
||||
# When adding additional environment variables, the schema in "/src/env.js"
|
||||
# should be updated accordingly.
|
||||
|
||||
# Example:
|
||||
# SERVERVAR="foo"
|
||||
# NEXT_PUBLIC_CLIENTVAR="bar"
|
40
.eslintrc.cjs
Normal file
@ -0,0 +1,40 @@
|
||||
/** @type {import("eslint").Linter.Config} */
|
||||
const config = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: true,
|
||||
},
|
||||
plugins: ['@typescript-eslint'],
|
||||
extends: [
|
||||
'next/core-web-vitals',
|
||||
'plugin:@typescript-eslint/recommended-type-checked',
|
||||
'plugin:@typescript-eslint/stylistic-type-checked',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/array-type': 'off',
|
||||
'@typescript-eslint/consistent-type-definitions': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'warn',
|
||||
{
|
||||
prefer: 'type-imports',
|
||||
fixStyle: 'inline-type-imports',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/require-await': 'off',
|
||||
'@typescript-eslint/no-misused-promises': [
|
||||
'error',
|
||||
{
|
||||
checksVoidReturn: {
|
||||
attributes: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
module.exports = config;
|
48
.gitignore
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# database
|
||||
/prisma/db.sqlite
|
||||
/prisma/db.sqlite-journal
|
||||
db.sqlite
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
next-env.d.ts
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
|
||||
.env
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
# idea files
|
||||
.idea
|
||||
# Sentry Config File
|
||||
.env.sentry-build-plugin
|
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"jsxSingleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
36
README.md
Normal file
@ -0,0 +1,36 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://techtracker.gibbyb.com"><img src="https://git.gibbyb.com/gib/Tech_Tracker_Web/raw/branch/master/public/images/tech_tracker_logo.png" alt="Tech Tracker Logo" width="100"></a>
|
||||
<br>
|
||||
<b>Tech Tracker</b>
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
# [Find Here](https://techtracker.gibbyb.com/)
|
||||
|
||||
- Application used by COG employees to update their status & location throughout the day.
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<h3>How to run:</h3>
|
||||
</summary>
|
||||
|
||||
I'd recommend installing pnpm. Clone the repo, then rename env.example to .env & fill it out.
|
||||
|
||||
```bash
|
||||
mv ./env.example ./.env
|
||||
```
|
||||
|
||||
Run
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
to install all dependencies.
|
||||
|
||||
You can run
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
53
docker/development/Dockerfile
Normal file
@ -0,0 +1,53 @@
|
||||
# syntax=docker.io/docker/dockerfile:1
|
||||
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# 1. Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
# 2. Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
# This will do the trick, use the corresponding env file for each environment.
|
||||
COPY .env .env.production
|
||||
RUN npm run build
|
||||
|
||||
# 3. Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN addgroup -g 1001 -S nodejs
|
||||
RUN adduser -S nextjs -u 1001
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT=3000
|
||||
|
||||
CMD HOSTNAME="0.0.0.0" node server.js
|
16
docker/development/compose.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
services:
|
||||
techtracker:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: docker/development/Dockerfile
|
||||
image: with-docker-multi-env-development
|
||||
container_name: techtracker
|
||||
networks:
|
||||
- node_apps
|
||||
ports:
|
||||
- '3004:3000'
|
||||
tty: true
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
node_apps:
|
||||
external: true
|
54
docker/production/Dockerfile
Normal file
@ -0,0 +1,54 @@
|
||||
# syntax=docker.io/docker/dockerfile:1
|
||||
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# 1. Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# 2. Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
# This will do the trick, use the corresponding env file for each environment.
|
||||
COPY .env .env.production
|
||||
RUN npm run build
|
||||
|
||||
# 3. Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN addgroup -g 1001 -S nodejs
|
||||
RUN adduser -S nextjs -u 1001
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT=3000
|
||||
|
||||
CMD HOSTNAME="0.0.0.0" node server.js
|
16
docker/production/compose.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
services:
|
||||
techtracker:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: docker/production/Dockerfile
|
||||
image: with-docker-multi-env-development
|
||||
container_name: techtracker
|
||||
networks:
|
||||
- node_apps
|
||||
ports:
|
||||
- '3004:3000'
|
||||
tty: true
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
node_apps:
|
||||
external: true
|
47
next.config.js
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
|
||||
* for Docker builds.
|
||||
*/
|
||||
import './src/env.js';
|
||||
|
||||
/** @type {import("next").NextConfig} */
|
||||
const config = {};
|
||||
|
||||
export default config;
|
||||
|
||||
// Injected content via Sentry wizard below
|
||||
|
||||
const { withSentryConfig } = require('@sentry/nextjs');
|
||||
|
||||
module.exports = withSentryConfig(module.exports, {
|
||||
// For all available options, see:
|
||||
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||
|
||||
org: 'gib',
|
||||
project: 'tech-tracker-next',
|
||||
sentryUrl: 'https://sentry.gbrown.org/',
|
||||
|
||||
// Only print logs for uploading source maps in CI
|
||||
silent: !process.env.CI,
|
||||
|
||||
// For all available options, see:
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
||||
|
||||
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
||||
widenClientFileUpload: true,
|
||||
|
||||
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
||||
// This can increase your server load as well as your hosting bill.
|
||||
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
||||
// side errors will fail.
|
||||
tunnelRoute: '/monitoring',
|
||||
|
||||
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||
disableLogger: true,
|
||||
|
||||
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
|
||||
// See the following for more information:
|
||||
// https://docs.sentry.io/product/crons/
|
||||
// https://vercel.com/docs/cron-jobs
|
||||
automaticVercelMonitors: true,
|
||||
});
|
47
package.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "tech-tracker-next",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"check": "next lint && tsc --noEmit",
|
||||
"dev": "next dev --turbo",
|
||||
"lint": "next lint",
|
||||
"lint:fix": "next lint --fix",
|
||||
"preview": "next build && next start",
|
||||
"start": "next start",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
||||
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/nextjs": "^9",
|
||||
"@supabase/supabase-js": "^2.49.1",
|
||||
"@t3-oss/env-nextjs": "^0.10.1",
|
||||
"geist": "^1.3.0",
|
||||
"next": "^15.0.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"zod": "^3.23.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/eslint": "^8.56.10",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.1.0",
|
||||
"@typescript-eslint/parser": "^8.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-next": "^15.0.1",
|
||||
"postcss": "^8.4.39",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"ct3aMetadata": {
|
||||
"initVersion": "7.38.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.5.2"
|
||||
}
|
7936
pnpm-lock.yaml
generated
Normal file
5
postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
4
prettier.config.js
Normal file
@ -0,0 +1,4 @@
|
||||
/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
|
||||
export default {
|
||||
plugins: ['prettier-plugin-tailwindcss'],
|
||||
};
|
BIN
public/favicon.ico
Executable file
After Width: | Height: | Size: 4.1 KiB |
1
public/images/authentik_logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 994.71 151.65"><defs><style>.cls-1{fill:#fd4b2d;}</style></defs><path class="cls-1" d="M284.72,50.4H305.5v82.84H284.72v-8.76a40.79,40.79,0,0,1-12.21,8.34,34.14,34.14,0,0,1-13.27,2.55q-16.05,0-27.76-12.45T219.77,92q0-19.18,11.33-31.45t27.53-12.26a34.94,34.94,0,0,1,14,2.82,38.32,38.32,0,0,1,12.1,8.45ZM262.87,67.45a21,21,0,0,0-16,6.82q-6.37,6.81-6.38,17.47T247,109.4a21,21,0,0,0,16,6.93,21.42,21.42,0,0,0,16.24-6.81q6.45-6.81,6.45-17.86,0-10.8-6.45-17.51A21.71,21.71,0,0,0,262.87,67.45Z"/><path class="cls-1" d="M335.8,50.4h21V90.29q0,11.65,1.6,16.18a14.16,14.16,0,0,0,5.16,7,14.76,14.76,0,0,0,8.74,2.51,15.25,15.25,0,0,0,8.81-2.48,14.49,14.49,0,0,0,5.38-7.27q1.31-3.57,1.3-15.3V50.4h20.79V85.5q0,21.69-3.43,29.69a32.32,32.32,0,0,1-12.33,15q-8.16,5.22-20.71,5.22-13.64,0-22.05-6.09a32.2,32.2,0,0,1-11.84-17q-2.43-7.55-2.43-27.41Z"/><path class="cls-1" d="M441.32,19.86H462.1V50.4h12.34V68.29H462.1v65H441.32V68.29H430.66V50.4h10.66Z"/><path class="cls-1" d="M495,18.42h20.63V58.77a47.41,47.41,0,0,1,12.26-7.88,31.62,31.62,0,0,1,12.49-2.63,28.13,28.13,0,0,1,20.78,8.53q7.23,7.4,7.24,21.7v54.75H547.9V96.92q0-14.4-1.37-19.49a13.6,13.6,0,0,0-4.68-7.62,13.19,13.19,0,0,0-8.18-2.51,15.43,15.43,0,0,0-10.85,4.19,22.14,22.14,0,0,0-6.28,11.42q-.91,3.72-.92,17v33.28H495Z"/><path class="cls-1" d="M680.84,97.83H614.06a22.25,22.25,0,0,0,7.73,14q6.29,5.22,16,5.21a27.7,27.7,0,0,0,20-8.14l17.51,8.22a41.31,41.31,0,0,1-15.68,13.74q-9.13,4.46-21.7,4.46-19.5,0-31.75-12.3T594,92.27q0-19,12.22-31.48t30.65-12.53q19.56,0,31.82,12.53t12.26,33.08ZM660.05,81.46a20.87,20.87,0,0,0-8.12-11.27,23.61,23.61,0,0,0-14.08-4.34,24.88,24.88,0,0,0-15.25,4.88q-4.11,3-7.62,10.73Z"/><path class="cls-1" d="M707,50.4H727.8v8.49a50.15,50.15,0,0,1,12.81-8.3,31.08,31.08,0,0,1,11.75-2.33,28.44,28.44,0,0,1,20.91,8.61q7.22,7.31,7.22,21.62v54.75H759.93V97q0-14.83-1.33-19.7A13.48,13.48,0,0,0,754,69.85a13,13,0,0,0-8.16-2.55A15.32,15.32,0,0,0,735,71.52a22.6,22.6,0,0,0-6.27,11.67q-.9,3.89-.91,16.81v33.24H707Z"/><path class="cls-1" d="M812.46,19.86h20.79V50.4h12.33V68.29H833.25v65H812.46V68.29H801.8V50.4h10.66Z"/><path class="cls-1" d="M874.16,16.29a12.74,12.74,0,0,1,9.38,3.95,13.18,13.18,0,0,1,3.91,9.6,13,13,0,0,1-3.87,9.48,12.6,12.6,0,0,1-9.27,3.92,12.73,12.73,0,0,1-9.45-4A13.39,13.39,0,0,1,861,29.53a12.78,12.78,0,0,1,3.87-9.36A12.71,12.71,0,0,1,874.16,16.29Z"/><rect class="cls-1" x="863.77" y="50.4" width="20.79" height="82.84"/><path class="cls-1" d="M913,18.42h20.78V84.55L964.34,50.4h26.11L954.76,90.1l40,43.14h-25.8L933.73,95.06v38.18H913Z"/><rect class="cls-1" x="107.1" y="34.93" width="6.37" height="18.2"/><rect class="cls-1" x="123.67" y="34.16" width="6.37" height="14.23"/><path class="cls-1" d="M30.83,55A23.23,23.23,0,0,0,10.41,67.13h10.8C26,63,32.94,61.8,38,67.13H49.39C44.93,61.09,38.24,55,30.83,55Z"/><path class="cls-1" d="M46.25,78.11c-14.89,31.15-41,4.6-25-11H10.41c-8.47,14.76,3.24,34.68,20.42,34.23,13.28,0,24.24-19.72,24.24-23.21,0-1.54-2.14-6.25-5.68-11H38A40.52,40.52,0,0,1,46.25,78.11Zm.4-.91Z"/><path class="cls-1" d="M189.62,34.71V117A28.62,28.62,0,0,1,161,145.54H148.89v-28H90.94v28H78.81A28.62,28.62,0,0,1,50.22,117V91.08h91.87V41.62H97.74V69.41H50.22V34.71a27.43,27.43,0,0,1,.19-3.29,27.09,27.09,0,0,1,.71-3.84c.1-.41.22-.82.34-1.21a2.13,2.13,0,0,1,.09-.3c.07-.21.13-.4.2-.59s.14-.4.21-.59.16-.44.25-.65.18-.43.26-.64a29.35,29.35,0,0,1,2.6-4.82l0-.05c.26-.37.53-.75.81-1.12s.47-.61.7-.91.57-.67.86-1,.56-.63.86-.93l0,0a4.53,4.53,0,0,1,.49-.49,29.23,29.23,0,0,1,3.4-2.84c.32-.24.66-.46,1-.68s.77-.49,1.17-.72a23.78,23.78,0,0,1,2.29-1.21l.75-.34a27.84,27.84,0,0,1,3.35-1.21c.44-.13.88-.24,1.33-.35a6.19,6.19,0,0,1,.65-.15,28.86,28.86,0,0,1,3.87-.57l.56,0h.28c.43,0,.87,0,1.31,0H161c.43,0,.87,0,1.3,0h.28l.56,0a29.25,29.25,0,0,1,3.88.57c.22,0,.43.09.65.15.45.11.88.22,1.32.35a27.23,27.23,0,0,1,3.35,1.21l.75.34a25.19,25.19,0,0,1,2.3,1.21c.39.23.78.47,1.16.72s.69.44,1,.68a29.23,29.23,0,0,1,3.91,3.36q.45.45.87.93c.29.32.57.66.85,1l.71.91c.28.37.54.75.8,1.12l0,.05a28.61,28.61,0,0,1,2.6,4.82l.27.64.24.65c.08.19.15.39.22.59l.19.59c0,.09.06.19.1.3.11.39.23.8.34,1.21a28.56,28.56,0,0,1,.7,3.84A27.42,27.42,0,0,1,189.62,34.71Z"/><path class="cls-1" d="M184.76,18.78H55.07A28.59,28.59,0,0,1,78.8,6.12H161A28.59,28.59,0,0,1,184.76,18.78Z"/><path class="cls-1" d="M189.43,31.43H50.4a28.29,28.29,0,0,1,4.67-12.65H184.76A28.17,28.17,0,0,1,189.43,31.43Z"/><path class="cls-1" d="M189.63,34.71v9.37H142.09V41.62H97.74v2.46H50.21V34.71a27.43,27.43,0,0,1,.19-3.29h139A27.42,27.42,0,0,1,189.63,34.71Z"/><rect class="cls-1" x="50.21" y="44.08" width="47.54" height="12.66"/><rect class="cls-1" x="142.09" y="44.08" width="47.54" height="12.66"/><rect class="cls-1" x="50.21" y="56.74" width="47.54" height="12.65"/><rect class="cls-1" x="142.09" y="56.74" width="47.54" height="12.65"/></svg>
|
After Width: | Height: | Size: 4.7 KiB |
BIN
public/images/default_user_pfp.png
Executable file
After Width: | Height: | Size: 126 KiB |
63
public/images/exit_fullscreen.svg
Executable file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg513"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="ExitFullscreen.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview515"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.4359982"
|
||||
inkscape:cx="69.108597"
|
||||
inkscape:cy="37.458519"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="3832"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs510" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 0,5.8620045 H 5.8615381 L 5.8621526,0 H 4.8849607 L 4.8846152,4.8851478 H 0 Z"
|
||||
id="path190"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 6.8384615,8.6556325e-4 V 5.8620045 H 12.7 V 4.8851478 H 7.815384 V 8.6556325e-4 Z"
|
||||
id="path396"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 12.7,6.8388612 H 6.8384615 V 12.7 H 7.815384 V 7.8157173 H 12.7 Z"
|
||||
id="path396-5"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193906"
|
||||
d="M 5.8615381,12.7 V 6.8388612 H 0 V 7.8157173 H 4.8846152 V 12.7 Z"
|
||||
id="path396-1"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
63
public/images/fullscreen.svg
Executable file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg513"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="Fullscreen.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview515"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.4359982"
|
||||
inkscape:cx="69.108597"
|
||||
inkscape:cy="37.458519"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="3832"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs510" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 5.8615386,0 H 0 V 5.8615386 H 0.97692256 V 0.97692327 H 5.8615386 Z"
|
||||
id="path396-6"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 0,6.8384619 V 12.7 H 5.8615386 V 11.723076 H 0.97692256 V 6.8384619 Z"
|
||||
id="path396-52"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 6.8384613,12.7 H 12.7 V 6.8384619 H 11.723078 V 11.723076 H 6.8384613 Z"
|
||||
id="path396-4"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke-width:0.193912"
|
||||
d="M 12.7,5.8615386 V 0 H 6.8384613 V 0.97692327 H 11.723078 V 5.8615386 Z"
|
||||
id="path396-0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/images/gitea_logo.png
Normal file
After Width: | Height: | Size: 16 KiB |
1
public/images/gitea_logo.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 640 640" width="32" height="32"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6M125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1m300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8s2 16.3 9.1 20c7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3s17.4 1.7 22.5-5.3c5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8z" style="fill:#609926"/></svg>
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/images/microsoft_logo.png
Executable file
After Width: | Height: | Size: 260 KiB |
1
public/images/microsoft_logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" width="779.07" height="141.73" viewBox="0 0 779.07 141.73"><title>Microsoft365_logo_horiz_c-gray_cmyk_horiz_c-gray_cmyk</title><g id="MS-symbol"><g><path d="M608.2,69.69v.19c5,.58,8.89,2.32,11.76,5.23a15,15,0,0,1,4.32,11,18.7,18.7,0,0,1-6.89,15.15q-6.9,5.75-18.74,5.74a41.61,41.61,0,0,1-9.44-1.08,23,23,0,0,1-7.08-2.62V92.11a25,25,0,0,0,7.56,4,27,27,0,0,0,8.71,1.51q6.44,0,10.19-3a9.94,9.94,0,0,0,3.72-8.14,9.39,9.39,0,0,0-4.41-8.39c-2.95-1.93-7.15-2.89-12.63-2.89h-6V65.61h5.71q7.26,0,11.18-2.7A8.92,8.92,0,0,0,610,55a9,9,0,0,0-3-7.32c-2-1.71-4.92-2.57-8.67-2.56a20.68,20.68,0,0,0-7,1.22,24.17,24.17,0,0,0-6.58,3.67V39.59a28.42,28.42,0,0,1,7.45-2.8,39.73,39.73,0,0,1,9.09-1q9,0,14.82,4.66a14.89,14.89,0,0,1,5.78,12.11,16.73,16.73,0,0,1-3.55,11A18.89,18.89,0,0,1,608.2,69.69Z" fill="#737474"></path><path d="M643,70a12.92,12.92,0,0,1,6.1-5.76,20.9,20.9,0,0,1,9.17-2,20,20,0,0,1,14,5.45q5.88,5.46,5.88,15.84,0,10.95-6.74,17.19a23.27,23.27,0,0,1-16.4,6.24q-11.28,0-17.76-8.38T630.8,75.22q0-19.5,8.61-29.48a27.4,27.4,0,0,1,21.64-10,50.12,50.12,0,0,1,7.24.47,18.64,18.64,0,0,1,5.33,1.49V48.13a26.26,26.26,0,0,0-6-2.26,25.55,25.55,0,0,0-6-.74A16.55,16.55,0,0,0,648,51.65q-5.15,6.52-5.24,18.32Zm.19,13.54a14.92,14.92,0,0,0,3.37,9.92,10.7,10.7,0,0,0,8.55,4A10.54,10.54,0,0,0,663.33,94q3.15-3.47,3.14-9.53,0-6.42-3.08-9.72A10.86,10.86,0,0,0,655,71.47a11.47,11.47,0,0,0-8.57,3.33,11.93,11.93,0,0,0-3.23,8.76Z" fill="#737474"></path><path d="M725.94,84.33q0,10.24-6.86,16.49T700.21,107a35.2,35.2,0,0,1-9.46-1.23,32.77,32.77,0,0,1-7-2.66V92.3a25.77,25.77,0,0,0,7.6,4,24.67,24.67,0,0,0,7.52,1.27q6.87,0,11-3.41A11.33,11.33,0,0,0,714,84.91,10.5,10.5,0,0,0,709.79,76q-4.24-3.18-12.22-3.17c-1.57,0-3.62.07-6.17.21s-4.3.28-5.26.41L688.59,37h34.23v9.86H698.19l-1.13,16.77c1.34-.11,2.38-.16,3.09-.17h3Q714,63.41,720,69T725.94,84.33Z" fill="#737474"></path></g><path d="M239.64,37v68.84h-12V51.87h-.19l-21.36,54h-7.92L176.29,51.87h-.14v54h-11V37h17.14L202,88h.29l20.89-51Zm10,5.23a6.33,6.33,0,0,1,2.09-4.82,7.41,7.41,0,0,1,10.06,0,6.58,6.58,0,0,1,2,4.78A6.21,6.21,0,0,1,261.74,47a7.07,7.07,0,0,1-5,1.92,7,7,0,0,1-5-1.93,6.29,6.29,0,0,1-2.08-4.74Zm12.82,14.27v49.37H250.82V56.48ZM297.7,97.37a15.76,15.76,0,0,0,5.67-1.19A24,24,0,0,0,309.13,93v10.81a23.43,23.43,0,0,1-6.31,2.4,34.86,34.86,0,0,1-7.76.82q-10.89,0-17.7-6.9t-6.82-17.59q0-11.89,7-19.56t19.72-7.8a27.28,27.28,0,0,1,6.61.84,22,22,0,0,1,5.3,2V69.17a23.31,23.31,0,0,0-5.5-3A15.8,15.8,0,0,0,297.9,65a14.55,14.55,0,0,0-11.09,4.46q-4.23,4.47-4.22,12.06t4.05,11.66q4,4.17,11,4.15Zm44.51-41.71a14,14,0,0,1,2.5.19,10,10,0,0,1,1.86.48V68.09a10.17,10.17,0,0,0-2.66-1.27,13.33,13.33,0,0,0-4.25-.6,9.05,9.05,0,0,0-7.23,3.6q-3,3.6-2.95,11.09v24.91H317.9V56.45h11.61v7.77h.2A13.55,13.55,0,0,1,334.48,58,13,13,0,0,1,342.21,55.66Zm5,26.21q0-12.24,6.92-19.39t19.21-7.16q11.57,0,18.07,6.89t6.52,18.63q0,12-6.91,19.11t-18.82,7.1q-11.47,0-18.21-6.74T347.2,81.87Zm12.12-.39q0,7.74,3.5,11.81t10,4.08q6.34,0,9.65-4.08t3.32-12.11q0-8-3.44-12t-9.62-4.07q-6.39,0-9.91,4.25t-3.55,12.14Zm55.89-12a5,5,0,0,0,1.59,3.91q1.59,1.41,7,3.58,7,2.79,9.76,6.26a12.91,12.91,0,0,1,2.8,8.38A13.52,13.52,0,0,1,431,102.75Q425.66,107,416.54,107a35.4,35.4,0,0,1-6.8-.75,30.18,30.18,0,0,1-6.3-1.86V93a28.2,28.2,0,0,0,6.82,3.5,19.93,19.93,0,0,0,6.62,1.3,11.83,11.83,0,0,0,5.8-1.1,4,4,0,0,0,1.87-3.73,5.11,5.11,0,0,0-1.94-4.05,29,29,0,0,0-7.37-3.82q-6.45-2.69-9.13-6a13.21,13.21,0,0,1-2.68-8.55,13.47,13.47,0,0,1,5.3-11q5.31-4.3,13.76-4.31a33.14,33.14,0,0,1,5.8.57,25.88,25.88,0,0,1,5.38,1.49V68.33a25.11,25.11,0,0,0-5.38-2.64,17.89,17.89,0,0,0-6.05-1.11,8.82,8.82,0,0,0-5.16,1.31,4.1,4.1,0,0,0-1.9,3.55Zm26.17,12.43q0-12.24,6.91-19.39t19.2-7.16q11.58,0,18.08,6.89t6.52,18.63q0,12-6.91,19.11t-18.83,7.1q-11.48,0-18.21-6.74t-6.79-18.44Zm12.11-.39q0,7.74,3.51,11.81T467,97.37q6.33,0,9.65-4.08t3.31-12.11q0-8-3.43-12t-9.63-4.07q-6.37,0-9.91,4.25t-3.49,12.14ZM530.64,66H513.29v39.84H501.53V66h-8.26v-9.5h8.26V49.6a17.06,17.06,0,0,1,5.06-12.74,17.82,17.82,0,0,1,13-5,29.06,29.06,0,0,1,3.73.22,15,15,0,0,1,2.88.65v10a13.26,13.26,0,0,0-2-.82,10.54,10.54,0,0,0-3.3-.47,7,7,0,0,0-5.59,2.28q-2,2.28-2,6.74v6h17.3V45.38l11.67-3.55V56.48H554V66H542.26V89.07q0,4.56,1.65,6.43t5.21,1.87a7.66,7.66,0,0,0,2.42-.48A11.92,11.92,0,0,0,554,95.73v9.61a14.24,14.24,0,0,1-3.67,1.15,26.12,26.12,0,0,1-5.07.53q-7.35,0-11-3.92t-3.67-11.78Z" fill="#737474"></path><rect x="15.94" y="14.03" width="54.53" height="54.53" fill="#f05125"></rect><rect x="76.14" y="14.03" width="54.53" height="54.53" fill="#7ebb42"></rect><rect x="15.94" y="74.24" width="54.53" height="54.53" fill="#33a0da"></rect><rect x="76.14" y="74.24" width="54.53" height="54.53" fill="#fdb813"></rect></g></svg>
|
After Width: | Height: | Size: 4.6 KiB |
BIN
public/images/tech_tracker_appicon.png
Executable file
After Width: | Height: | Size: 98 KiB |
BIN
public/images/tech_tracker_favicon.png
Executable file
After Width: | Height: | Size: 5.2 KiB |
BIN
public/images/tech_tracker_logo.png
Executable file
After Width: | Height: | Size: 386 KiB |
105
scripts/files_to_clipboard.py
Executable file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import pyperclip
|
||||
import questionary
|
||||
|
||||
# List of directories to exclude
|
||||
EXCLUDED_DIRS = {'node_modules', '.next', '.venv', '.git', '__pycache__', '.idea', '.vscode', 'ui'}
|
||||
|
||||
def collect_files(project_path):
|
||||
"""
|
||||
Collects files from the project directory, excluding specified directories and filtering by extensions.
|
||||
Returns a list of file paths relative to the project directory.
|
||||
"""
|
||||
collected_files = []
|
||||
|
||||
for root, dirs, files in os.walk(project_path):
|
||||
# Exclude specified directories
|
||||
dirs[:] = [d for d in dirs if d not in EXCLUDED_DIRS]
|
||||
|
||||
for file in files:
|
||||
file_path = Path(root) / file
|
||||
relative_path = file_path.relative_to(project_path)
|
||||
collected_files.append(relative_path)
|
||||
|
||||
return collected_files
|
||||
|
||||
def main():
|
||||
# Parse command-line arguments
|
||||
parser = argparse.ArgumentParser(description='Generate Markdown from selected files.')
|
||||
parser.add_argument('path', nargs='?', default='.', help='Path to the project directory')
|
||||
args = parser.parse_args()
|
||||
|
||||
project_path = Path(args.path).resolve()
|
||||
if not project_path.is_dir():
|
||||
print(f"Error: '{project_path}' is not a directory.")
|
||||
sys.exit(1)
|
||||
|
||||
# Collect files from the project directory
|
||||
file_list = collect_files(project_path)
|
||||
|
||||
if not file_list:
|
||||
print("No files found in the project directory with the specified extensions.")
|
||||
sys.exit(1)
|
||||
|
||||
# Sort file_list for better organization
|
||||
file_list.sort()
|
||||
|
||||
# Interactive file selection using questionary
|
||||
print("\nSelect the files you want to include:")
|
||||
selected_files = questionary.checkbox(
|
||||
"Press space to select files, and Enter when you're done:",
|
||||
choices=[str(f) for f in file_list]
|
||||
).ask()
|
||||
|
||||
if not selected_files:
|
||||
print("No files selected.")
|
||||
sys.exit(1)
|
||||
|
||||
# Generate markdown
|
||||
markdown_lines = []
|
||||
markdown_lines.append('')
|
||||
|
||||
for selected_file in selected_files:
|
||||
file_path = project_path / selected_file
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
# Determine the language for code block from file extension
|
||||
language = file_path.suffix.lstrip('.')
|
||||
markdown_lines.append(f'{selected_file}')
|
||||
markdown_lines.append(f'```{language}')
|
||||
markdown_lines.append(content)
|
||||
markdown_lines.append('```')
|
||||
markdown_lines.append('')
|
||||
except Exception as e:
|
||||
print(f"Error reading file {selected_file}: {e}")
|
||||
|
||||
markdown_text = '\n'.join(markdown_lines)
|
||||
|
||||
# Write markdown to file
|
||||
output_file = 'output.md'
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(markdown_text)
|
||||
print(f"\nMarkdown file '{output_file}' has been generated.")
|
||||
|
||||
# Copy markdown content to clipboard
|
||||
pyperclip.copy(markdown_text)
|
||||
print("Markdown content has been copied to the clipboard.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Check if required libraries are installed
|
||||
try:
|
||||
import questionary
|
||||
import pyperclip
|
||||
except ImportError as e:
|
||||
missing_module = e.name
|
||||
print(f"Error: Missing required module '{missing_module}'.")
|
||||
print(f"Please install it by running: pip install {missing_module}")
|
||||
sys.exit(1)
|
||||
|
||||
main()
|
18
scripts/next.config.build.js
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
|
||||
* for Docker builds.
|
||||
*/
|
||||
import './src/env.js';
|
||||
|
||||
/** @type {import("next").NextConfig} */
|
||||
const config = {
|
||||
output: 'standalone',
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
49
scripts/next.config.default.js
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
|
||||
* for Docker builds.
|
||||
*/
|
||||
import './src/env.js';
|
||||
|
||||
/** @type {import("next").NextConfig} */
|
||||
const config = {
|
||||
output: 'standalone',
|
||||
};
|
||||
|
||||
export default config;
|
||||
/**
|
||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
|
||||
* for Docker builds.
|
||||
*/
|
||||
//await import("./src/env.js");
|
||||
|
||||
//const cspHeader = `
|
||||
//default-src 'self';
|
||||
//script-src 'self' 'unsafe-eval' 'unsafe-inline';
|
||||
//style-src 'self' 'unsafe-inline';
|
||||
//img-src 'self' blob: data:;
|
||||
//font-src 'self';
|
||||
//object-src 'none';
|
||||
//base-uri 'self';
|
||||
//form-action 'self';
|
||||
//frame-ancestors 'none';
|
||||
//upgrade-insecure-requests;
|
||||
//`
|
||||
|
||||
//[>* @type {import("next").NextConfig} <]
|
||||
//const config = {
|
||||
//async headers() {
|
||||
//return [
|
||||
//{
|
||||
//source: "/(.*)",
|
||||
//headers: [
|
||||
//{
|
||||
//key: "Content-Security-Policy",
|
||||
//value: cspHeader.replace(/\n/g, ''),
|
||||
//},
|
||||
//],
|
||||
//},
|
||||
//];
|
||||
//},
|
||||
//};
|
||||
|
||||
//export default config;
|
7
scripts/reload_container.sh
Executable file
@ -0,0 +1,7 @@
|
||||
git pull
|
||||
mv ~/Documents/Web/Tech_Tracker_Web/next.config.js ~/Documents/Web/Tech_Tracker_Web/scripts/next.config.default.js
|
||||
cp ~/Documents/Web/Tech_Tracker_Web/scripts/next.config.build.js ~/Documents/Web/Tech_Tracker_Web/next.config.js
|
||||
sudo docker compose -f docker/development/compose.yaml down
|
||||
sudo docker compose -f docker/development/compose.yaml build
|
||||
sudo docker compose -f docker/development/compose.yaml up -d
|
||||
cp ~/Documents/Web/Tech_Tracker_Web/scripts/next.config.default.js ~/Documents/Web/Tech_Tracker_Web/next.config.js
|
26
sentry.client.config.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// This file configures the initialization of Sentry on the client.
|
||||
// The config you add here will be used whenever a users loads a page in their browser.
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://c73de96b2ba3248b5a22dd156b05b334@sentry.gbrown.org/4',
|
||||
|
||||
// Add optional integrations for additional features
|
||||
integrations: [Sentry.replayIntegration()],
|
||||
|
||||
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
|
||||
tracesSampleRate: 1,
|
||||
|
||||
// Define how likely Replay events are sampled.
|
||||
// This sets the sample rate to be 10%. You may want this to be 100% while
|
||||
// in development and sample at a lower rate in production
|
||||
replaysSessionSampleRate: 0.1,
|
||||
|
||||
// Define how likely Replay events are sampled when an error occurs.
|
||||
replaysOnErrorSampleRate: 1.0,
|
||||
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
});
|
16
sentry.edge.config.ts
Normal file
@ -0,0 +1,16 @@
|
||||
// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).
|
||||
// The config you add here will be used whenever one of the edge features is loaded.
|
||||
// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://c73de96b2ba3248b5a22dd156b05b334@sentry.gbrown.org/4',
|
||||
|
||||
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
|
||||
tracesSampleRate: 1,
|
||||
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
});
|
15
sentry.server.config.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// This file configures the initialization of Sentry on the server.
|
||||
// The config you add here will be used whenever the server handles a request.
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://c73de96b2ba3248b5a22dd156b05b334@sentry.gbrown.org/4',
|
||||
|
||||
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
|
||||
tracesSampleRate: 1,
|
||||
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
});
|
9
src/app/api/sentry-example-api/route.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
// A faulty API route to test Sentry's error monitoring
|
||||
export function GET() {
|
||||
throw new Error('Sentry Example API Route Error');
|
||||
return NextResponse.json({ data: 'Testing Sentry Error...' });
|
||||
}
|
27
src/app/global-error.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
'use client';
|
||||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import NextError from 'next/error';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export default function GlobalError({
|
||||
error,
|
||||
}: {
|
||||
error: Error & { digest?: string };
|
||||
}) {
|
||||
useEffect(() => {
|
||||
Sentry.captureException(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<html>
|
||||
<body>
|
||||
{/* `NextError` is the default Next.js error page component. Its type
|
||||
definition requires a `statusCode` prop. However, since the App Router
|
||||
does not expose status codes for errors, we simply pass 0 to render a
|
||||
generic error message. */}
|
||||
<NextError statusCode={0} />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
20
src/app/layout.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import '@/styles/globals.css';
|
||||
|
||||
import { GeistSans } from 'geist/font/sans';
|
||||
import { type Metadata } from 'next';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Create T3 App',
|
||||
description: 'Generated by create-t3-app',
|
||||
icons: [{ rel: 'icon', url: '/favicon.ico' }],
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{ children: React.ReactNode }>) {
|
||||
return (
|
||||
<html lang='en' className={`${GeistSans.variable}`}>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
37
src/app/page.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<main className='flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white'>
|
||||
<div className='container flex flex-col items-center justify-center gap-12 px-4 py-16'>
|
||||
<h1 className='text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]'>
|
||||
Create <span className='text-[hsl(280,100%,70%)]'>T3</span> App
|
||||
</h1>
|
||||
<div className='grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8'>
|
||||
<Link
|
||||
className='flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20'
|
||||
href='https://create.t3.gg/en/usage/first-steps'
|
||||
target='_blank'
|
||||
>
|
||||
<h3 className='text-2xl font-bold'>First Steps →</h3>
|
||||
<div className='text-lg'>
|
||||
Just the basics - Everything you need to know to set up your
|
||||
database and authentication.
|
||||
</div>
|
||||
</Link>
|
||||
<Link
|
||||
className='flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20'
|
||||
href='https://create.t3.gg/en/introduction'
|
||||
target='_blank'
|
||||
>
|
||||
<h3 className='text-2xl font-bold'>Documentation →</h3>
|
||||
<div className='text-lg'>
|
||||
Learn more about Create T3 App, the libraries it uses, and how to
|
||||
deploy it.
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
85
src/app/sentry-example-page/page.tsx
Normal file
@ -0,0 +1,85 @@
|
||||
'use client';
|
||||
|
||||
import Head from 'next/head';
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>Sentry Onboarding</title>
|
||||
<meta name='description' content='Test Sentry for your Next.js app!' />
|
||||
</Head>
|
||||
|
||||
<main
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<h1 style={{ fontSize: '4rem', margin: '14px 0' }}>
|
||||
<svg
|
||||
style={{
|
||||
height: '1em',
|
||||
}}
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='0 0 200 44'
|
||||
>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z'
|
||||
></path>
|
||||
</svg>
|
||||
</h1>
|
||||
|
||||
<p>Get started by sending us a sample error:</p>
|
||||
<button
|
||||
type='button'
|
||||
style={{
|
||||
padding: '12px',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: '#AD6CAA',
|
||||
borderRadius: '4px',
|
||||
border: 'none',
|
||||
color: 'white',
|
||||
fontSize: '14px',
|
||||
margin: '18px',
|
||||
}}
|
||||
onClick={async () => {
|
||||
await Sentry.startSpan(
|
||||
{
|
||||
name: 'Example Frontend Span',
|
||||
op: 'test',
|
||||
},
|
||||
async () => {
|
||||
const res = await fetch('/api/sentry-example-api');
|
||||
if (!res.ok) {
|
||||
throw new Error('Sentry Example Frontend Error');
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
>
|
||||
Throw error!
|
||||
</button>
|
||||
|
||||
<p>
|
||||
Next, look for the error on the{' '}
|
||||
<a href='https://sentry.gbrown.org/organizations/gib/issues/?project=4'>
|
||||
Issues Page
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<p style={{ marginTop: '24px' }}>
|
||||
For more information, see{' '}
|
||||
<a href='https://docs.sentry.io/platforms/javascript/guides/nextjs/'>
|
||||
https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
</a>
|
||||
</p>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
40
src/env.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { createEnv } from '@t3-oss/env-nextjs';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const env = createEnv({
|
||||
/**
|
||||
* Specify your server-side environment variables schema here. This way you can ensure the app
|
||||
* isn't built with invalid env vars.
|
||||
*/
|
||||
server: {
|
||||
NODE_ENV: z.enum(['development', 'test', 'production']),
|
||||
},
|
||||
|
||||
/**
|
||||
* Specify your client-side environment variables schema here. This way you can ensure the app
|
||||
* isn't built with invalid env vars. To expose them to the client, prefix them with
|
||||
* `NEXT_PUBLIC_`.
|
||||
*/
|
||||
client: {
|
||||
// NEXT_PUBLIC_CLIENTVAR: z.string(),
|
||||
},
|
||||
|
||||
/**
|
||||
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
|
||||
* middlewares) or client-side so we need to destruct manually.
|
||||
*/
|
||||
runtimeEnv: {
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
|
||||
},
|
||||
/**
|
||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
|
||||
* useful for Docker builds.
|
||||
*/
|
||||
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
|
||||
/**
|
||||
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
|
||||
* `SOME_VAR=''` will throw an error.
|
||||
*/
|
||||
emptyStringAsUndefined: true,
|
||||
});
|
13
src/instrumentation.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
export async function register() {
|
||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
||||
await import('../sentry.server.config');
|
||||
}
|
||||
|
||||
if (process.env.NEXT_RUNTIME === 'edge') {
|
||||
await import('../sentry.edge.config');
|
||||
}
|
||||
}
|
||||
|
||||
export const onRequestError = Sentry.captureRequestError;
|
3
src/styles/globals.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
14
tailwind.config.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { type Config } from 'tailwindcss';
|
||||
import { fontFamily } from 'tailwindcss/defaultTheme';
|
||||
|
||||
export default {
|
||||
content: ['./src/**/*.tsx'],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['var(--font-geist-sans)', ...fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
} satisfies Config;
|
42
tsconfig.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Base Options: */
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"target": "es2022",
|
||||
"allowJs": true,
|
||||
"resolveJsonModule": true,
|
||||
"moduleDetection": "force",
|
||||
"isolatedModules": true,
|
||||
|
||||
/* Strictness */
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"checkJs": true,
|
||||
|
||||
/* Bundled projects */
|
||||
"lib": ["dom", "dom.iterable", "ES2022"],
|
||||
"noEmit": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"jsx": "preserve",
|
||||
"plugins": [{ "name": "next" }],
|
||||
"incremental": true,
|
||||
|
||||
/* Path Aliases */
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
".eslintrc.cjs",
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.cjs",
|
||||
"**/*.js",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|