Merge branch '@feature/proper_auth' into develop
@@ -1,25 +0,0 @@
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/.idea
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
5
.env.development
Normal file
@@ -0,0 +1,5 @@
|
||||
NEXTAUTH_SECRET=FOo84lSFySlsU19WXv+RWE2N54PyeigBMJWxAiZucw0=
|
||||
NEXTAUTH_URL=https://nukeitter.dev.fergl.ie:3000
|
||||
|
||||
TWITTER_CLIENT_ID=U1VDNWl0eHNhLW1MN2lDN1gyOGI6MTpjaQ
|
||||
TWITTER_CLIENT_SECRET=TNwtd1iNnwU9uZeZWd7k7DtNQN1z0X0fCljvxd-lLHGhm3U9Nb
|
||||
3
.eslintrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
||||
41
.gitignore
vendored
@@ -1,5 +1,36 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
13
.idea/.idea.nukeitter-web.dir/.idea/.gitignore
generated
vendored
@@ -1,13 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/projectSettingsUpdater.xml
|
||||
/modules.xml
|
||||
/contentModel.xml
|
||||
/.idea.nukeitter-web.iml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/.idea.nukeitter-web.dir/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
13
.idea/.idea.nukitter-web/.idea/.gitignore
generated
vendored
@@ -1,13 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/projectSettingsUpdater.xml
|
||||
/modules.xml
|
||||
/contentModel.xml
|
||||
/.idea.nukitter-web.iml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
4
.idea/.idea.nukitter-web/.idea/encodings.xml
generated
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
||||
8
.idea/.idea.nukitter-web/.idea/indexLayout.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<file url="PROJECT" libraries="{daisyui}" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/.idea.nukitter-web/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
16
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"program": "${workspaceFolder}/server.js",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
||||
147529
.yarn/releases/yarn-1.22.19.cjs
vendored
Executable file
1
.yarnrc.yml
Normal file
@@ -0,0 +1 @@
|
||||
yarnPath: .yarn/releases/yarn-1.22.19.cjs
|
||||
14
App.razor
@@ -1,14 +0,0 @@
|
||||
<CascadingAuthenticationState>
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
</CascadingAuthenticationState>
|
||||
@@ -1,16 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Twitter;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Nukitter.Web.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class UserController : ControllerBase {
|
||||
[HttpGet("twitter")]
|
||||
public async Task TwitterSignIn() {
|
||||
await HttpContext.ChallengeAsync(TwitterDefaults.AuthenticationScheme, new AuthenticationProperties {
|
||||
RedirectUri = "https://nukeitter.dev.fergl.ie:5001/profile"
|
||||
});
|
||||
}
|
||||
}
|
||||
20
Dockerfile
@@ -1,20 +0,0 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["nukitter-web.csproj", "./"]
|
||||
RUN dotnet restore "nukitter-web.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/"
|
||||
RUN dotnet build "nukitter-web.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "nukitter-web.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "nukitter-web.dll"]
|
||||
@@ -1,18 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
<PageTitle>Counter</PageTitle>
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p role="status">Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount() {
|
||||
currentCount++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
@page
|
||||
@model Nukitter.Web.Pages.ErrorModel
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||
<title>Error</title>
|
||||
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link href="~/css/site.css" rel="stylesheet" asp-append-version="true"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="main">
|
||||
<div class="content px-4">
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId) {
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace Nukitter.Web.Pages;
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public class ErrorModel : PageModel {
|
||||
public string? RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
private readonly ILogger<ErrorModel> _logger;
|
||||
|
||||
public ErrorModel(ILogger<ErrorModel> logger) {
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void OnGet() {
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
@page "/"
|
||||
|
||||
<PageTitle>Twit Nuke</PageTitle>
|
||||
|
||||
<div
|
||||
class="container mx-auto flex flex-col md:flex-row items-center my-12 md:my-24">
|
||||
<!--Left Col-->
|
||||
<div
|
||||
class="flex flex-col w-full lg:w-1/2 justify-center items-start pt-12 pb-24 px-6 group">
|
||||
<p class="uppercase tracking-loose">Nukeitter</p>
|
||||
<div class="group flex justify-center items-center">
|
||||
<h1 class="font-bold text-3xl my-4 flx flex-row">
|
||||
Delete your Tweets on a schedule... or just once.
|
||||
</h1>
|
||||
</div>
|
||||
<p class="leading-normal mb-4">
|
||||
You never know who's gonna read that radioactive Tweet you forgot you sent
|
||||
in 2017
|
||||
</p>
|
||||
<a
|
||||
href="/setup"
|
||||
class="btn btn-outline btn-info gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.59 14.37a6 6 0 01-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 006.16-12.12A14.98 14.98 0 009.631 8.41m5.96 5.96a14.926 14.926 0 01-5.841 2.58m-.119-8.54a6 6 0 00-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 00-2.58 5.84m2.699 2.7c-.103.021-.207.041-.311.06a15.09 15.09 0 01-2.448-2.448 14.9 14.9 0 01.06-.312m-2.24 2.39a4.493 4.493 0 00-1.757 4.306 4.493 4.493 0 004.306-1.758M16.5 9a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z"/>
|
||||
</svg>
|
||||
|
||||
Let's go
|
||||
</a>
|
||||
</div>
|
||||
<!--Right Col-->
|
||||
<div class="w-full lg:w-1/2 lg:py-6 text-center">
|
||||
<img
|
||||
src="/img/logo.svg"
|
||||
alt="Radioactive"
|
||||
class="fill-current text-gray-900 w-3/5 mx-auto"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,31 +0,0 @@
|
||||
@page "/profile"
|
||||
@using System.Security.Claims
|
||||
@inject NavigationManager _navigationManager
|
||||
|
||||
<PageTitle>Twit Nuke</PageTitle>
|
||||
|
||||
<div
|
||||
class="container mx-auto flex flex-col md:flex-row items-center my-12 md:my-24">
|
||||
<h1>This is your profile</h1>
|
||||
<div>@claim</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
[CascadingParameter]
|
||||
public Task<AuthenticationState> authenticationState { get; set; }
|
||||
|
||||
public Claim claim;
|
||||
|
||||
protected override async Task OnInitializedAsync() {
|
||||
var authState = await authenticationState;
|
||||
var user = authState.User;
|
||||
|
||||
if (user.Identity.IsAuthenticated) {
|
||||
claim = user.FindFirst(c => c.Type == ClaimTypes.NameIdentifier);
|
||||
}
|
||||
else {
|
||||
_navigationManager.NavigateTo("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
@page "/setup"
|
||||
@inject NavigationManager _navigationManager
|
||||
|
||||
<PageTitle>Twit Nuke</PageTitle>
|
||||
|
||||
<div
|
||||
class="container mx-auto flex flex-col md:flex-row items-center my-12 md:my-24">
|
||||
<!--Left Col-->
|
||||
<div
|
||||
class="flex flex-col w-full lg:w-1/2 justify-center items-start pt-12 pb-24 px-6 group">
|
||||
<div class="group flex justify-center items-center">
|
||||
<h1 class="font-bold text-3xl my-4 flx flex-row">
|
||||
Let's get started
|
||||
</h1>
|
||||
</div>
|
||||
<p class="leading-normal mb-4">
|
||||
We need access to your Twitter account, promise we won't do anything icky!!
|
||||
</p>
|
||||
<button
|
||||
@onclick="TwitterSignin"
|
||||
href="/setup"
|
||||
class="btn btn-outline btn-info gap-2">
|
||||
<i class="fa-brands fa-twitter"></i>
|
||||
Login to Twitter
|
||||
</button>
|
||||
</div>
|
||||
<!--Right Col-->
|
||||
<div class="w-full lg:w-1/2 lg:py-6 text-center">
|
||||
<img
|
||||
src="/img/logo.svg"
|
||||
alt="Radioactive"
|
||||
class="fill-current text-gray-900 w-3/5 mx-auto"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
private void TwitterSignin() {
|
||||
_navigationManager.NavigateTo("user/twitter", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
@page "/"
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@namespace Nukitter.Web.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@addTagHelper *, Heroicons.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<base href="~/"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@2.47.0/dist/full.css" rel="stylesheet" type="text/css"/>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha512-MV7K8+y+gLIBoVD59lQIYicR65iaqukzvf/nwasF0nqhPay5w/9lJmVM2hMDcnK1OnMGCdVK+iQrJ7lzPJQd1w==" crossorigin="anonymous" referrerpolicy="no-referrer"/>
|
||||
<link rel="icon" type="image/png" href="favicon.ico"/>
|
||||
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>
|
||||
</head>
|
||||
<body>
|
||||
<component type="typeof(App)" render-mode="ServerPrerendered"/>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
<environment include="Staging,Production">
|
||||
An error has occurred. This application may no longer respond until reloaded.
|
||||
</environment>
|
||||
<environment include="Development">
|
||||
An unhandled exception has occurred. See browser dev tools for details.
|
||||
</environment>
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
47
Program.cs
@@ -1,47 +0,0 @@
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.WebHost.ConfigureKestrel(options => {
|
||||
options.Listen(IPAddress.Any, 5001, listenOptions => {
|
||||
var certPem = File.ReadAllText("/etc/letsencrypt/live/dev.fergl.ie/fullchain.pem");
|
||||
var keyPem = File.ReadAllText("/etc/letsencrypt/live/dev.fergl.ie/privkey.pem");
|
||||
var x509 = X509Certificate2.CreateFromPem(certPem, keyPem);
|
||||
listenOptions.UseHttps(x509);
|
||||
});
|
||||
});
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
|
||||
builder.Services.AddAuthentication(options => {
|
||||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie()
|
||||
.AddTwitter(twitterOptions => {
|
||||
twitterOptions.ConsumerKey = builder.Configuration["Auth:Twitter:ConsumerKey"];
|
||||
twitterOptions.ConsumerSecret = builder.Configuration["Auth:Twitter:ConsumerSecret"];
|
||||
twitterOptions.RetrieveUserDetails = true;
|
||||
});
|
||||
builder.Services.AddControllers();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (!app.Environment.IsDevelopment()) {
|
||||
app.UseExceptionHandler("/Error");
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
|
||||
app.Run();
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:33728",
|
||||
"sslPort": 44341
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:5001",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
|
||||
|
||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
@@ -1,15 +0,0 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<PageTitle>nukitter-web</PageTitle>
|
||||
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu/>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<article class="content px-4">
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
@@ -1,70 +0,0 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.top-row a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row:not(.auth) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-row.auth {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row a, .top-row .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<div class="navbar bg-base-100">
|
||||
<div class="flex-none">
|
||||
<img
|
||||
src="/img/logo.svg"
|
||||
alt="Radioactive"
|
||||
class="fill-current text-gray-900 w-8 h-8 mx-auto"/>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<a class="btn btn-ghost normal-case text-xl">NukeTwitter</a>
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
<span>Stuff on the right</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,68 +0,0 @@
|
||||
.navbar-toggler {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.oi {
|
||||
width: 2rem;
|
||||
font-size: 1.1rem;
|
||||
vertical-align: text-top;
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.25);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep a:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<div class="alert alert-secondary mt-4">
|
||||
<span class="oi oi-pencil me-2" aria-hidden="true"></span>
|
||||
<strong>@Title</strong>
|
||||
|
||||
<span class="text-nowrap">
|
||||
Please take our
|
||||
<a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2186158">brief survey</a>
|
||||
</span>
|
||||
and tell us what you think.
|
||||
</div>
|
||||
|
||||
@code {
|
||||
// Demonstrates how a parent component can supply parameters
|
||||
[Parameter]
|
||||
public string? Title { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
@using System.Net.Http
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using Nukitter.Web
|
||||
@using Nukitter.Web.Shared
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Auth": {
|
||||
"Twitter": {
|
||||
"ConsumerKey": "wRE6ajw7rraqDax8iOhZCHvml",
|
||||
"ConsumerSecret": "l4Jn42ON1BrN8N4L28unQJYcjcRpbWuMIfcwzZZx3Dg8ZipyoD"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
next.config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
experimental: {
|
||||
appDir: true,
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
@@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>Nukitter.Web</RootNamespace>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Twitter" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
32
package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "nukeitter",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "node ./server.js",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@next/font": "13.1.5",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/react": "18.0.27",
|
||||
"@types/react-dom": "18.0.10",
|
||||
"eslint": "8.32.0",
|
||||
"eslint-config-next": "13.1.5",
|
||||
"next": "13.1.5",
|
||||
"next-auth": "^4.18.8",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-icons": "^4.7.1",
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.13",
|
||||
"daisyui": "^2.47.0",
|
||||
"postcss": "^8.4.21",
|
||||
"tailwindcss": "^3.2.4"
|
||||
},
|
||||
"packageManager": "yarn@1.22.19"
|
||||
}
|
||||
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 774 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
23
server.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const https = require("https");
|
||||
const fs = require("fs");
|
||||
|
||||
const next = require("next");
|
||||
const port = 3000;
|
||||
const dev = process.env.NODE_ENV !== "production";
|
||||
const hostname = "nukeitter.dev.fergl.ie";
|
||||
const app = next({ dev, hostname, port, dir: __dirname });
|
||||
const handle = app.getRequestHandler();
|
||||
|
||||
const options = {
|
||||
key: fs.readFileSync("/etc/letsencrypt/live/dev.fergl.ie/privkey.pem"),
|
||||
cert: fs.readFileSync("/etc/letsencrypt/live/dev.fergl.ie/fullchain.pem"),
|
||||
};
|
||||
|
||||
app.prepare().then(() => {
|
||||
https
|
||||
.createServer(options, (req, res) => handle(req, res))
|
||||
.listen(port, (err) => {
|
||||
if (err) throw err;
|
||||
console.log(`> Ready on localhost:${port}`);
|
||||
});
|
||||
});
|
||||
3
src/app/globals.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
10
src/app/head.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
export default function Head() {
|
||||
return (
|
||||
<>
|
||||
<title>NukeItter</title>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
<meta name="description" content="Delete Your Tweets!!" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
25
src/app/layout.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
import NavbarComponent from "@/components/layout/NavBar";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
import "./globals.css";
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" data-theme="cupcake">
|
||||
<head />
|
||||
<body>
|
||||
<SessionProvider>
|
||||
<NavbarComponent />
|
||||
|
||||
<main>
|
||||
<article className="px-4 content">{children}</article>
|
||||
</main>
|
||||
</SessionProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
0
src/app/page.module.css
Normal file
23
src/app/page.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
"use client";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { LoginPage, LoggedInPage } from "@/components/pages";
|
||||
import { LoadingSpinner } from "@/components/widgets";
|
||||
|
||||
export default function Home() {
|
||||
const session = useSession();
|
||||
const _getPage = () => {
|
||||
switch (session.status) {
|
||||
case "authenticated":
|
||||
return <LoggedInPage />;
|
||||
case "loading":
|
||||
return <LoadingSpinner />;
|
||||
case "unauthenticated":
|
||||
return <LoginPage />;
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="container flex flex-col items-center mx-auto my-12 md:flex-row md:my-24">
|
||||
{_getPage()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
11
src/app/setup/page.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from "react";
|
||||
|
||||
const SetupPage = () => {
|
||||
return (
|
||||
<div className="container flex flex-col items-center mx-auto my-4 md:flex-row md:my-8">
|
||||
SetupPage
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SetupPage;
|
||||
23
src/components/layout/NavBar.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
|
||||
const NavbarComponent = () => {
|
||||
return (
|
||||
<div className="navbar bg-base-100">
|
||||
<div className="flex-none">
|
||||
<img
|
||||
src="/img/logo.svg"
|
||||
alt="Radioactive"
|
||||
className="w-8 h-8 mx-auto text-gray-900 fill-current"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<a className="text-xl normal-case btn btn-ghost">NukeTwitter</a>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<span>Stuff on the right</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavbarComponent;
|
||||
9
src/components/pages/LoggedInPage.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
import { RiTwitterFill } from "react-icons/ri";
|
||||
import { signIn } from "next-auth/react";
|
||||
|
||||
const LoginPage = () => {
|
||||
return <React.Fragment>Good boy</React.Fragment>;
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
38
src/components/pages/LoginPage.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import { RiTwitterFill } from "react-icons/ri";
|
||||
import { signIn } from "next-auth/react";
|
||||
|
||||
const LoginPage = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="flex flex-col items-start justify-center w-full px-6 pt-12 pb-24 lg:w-1/2 group">
|
||||
<p className="uppercase tracking-loose">Nukeitter</p>
|
||||
<div className="flex items-center justify-center group">
|
||||
<h1 className="flex-row my-4 text-3xl font-bold flx">
|
||||
Delete your Tweets on a schedule... or just once.
|
||||
</h1>
|
||||
</div>
|
||||
<p className="mb-4 leading-normal">
|
||||
You never know who's gonna read that radioactive Tweet you forgot
|
||||
you sent in 2017
|
||||
</p>
|
||||
<button
|
||||
className="gap-2 btn btn-outline btn-info"
|
||||
onClick={() => signIn("twitter")}
|
||||
>
|
||||
<RiTwitterFill className="w-6 h-6" />
|
||||
Sign in with Twitter
|
||||
</button>
|
||||
</div>
|
||||
<div className="w-full text-center lg:w-1/2 lg:py-6">
|
||||
<img
|
||||
src="/img/logo.svg"
|
||||
alt="Radioactive"
|
||||
className="w-3/5 mx-auto text-gray-900 fill-current"
|
||||
/>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
4
src/components/pages/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import LoggedInPage from "./LoggedInPage";
|
||||
import LoginPage from "./LoginPage";
|
||||
|
||||
export { LoggedInPage, LoginPage };
|
||||
27
src/components/widgets/LoadingSpinner.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
|
||||
const LoadingSpinner = () => {
|
||||
return (
|
||||
<div role="status">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill"
|
||||
/>
|
||||
</svg>
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingSpinner;
|
||||
3
src/components/widgets/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import LoadingSpinner from "./LoadingSpinner";
|
||||
|
||||
export { LoadingSpinner };
|
||||
15
src/pages/api/auth/[...nextauth].js
Normal file
@@ -0,0 +1,15 @@
|
||||
import NextAuth from "next-auth";
|
||||
import TwitterProvider from "next-auth/providers/twitter";
|
||||
|
||||
export const authOptions = {
|
||||
// Configure one or more authentication providers
|
||||
providers: [
|
||||
TwitterProvider({
|
||||
clientId: process.env.TWITTER_CLIENT_ID,
|
||||
clientSecret: process.env.TWITTER_CLIENT_SECRET,
|
||||
version: "2.0",
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default NextAuth(authOptions);
|
||||
13
src/pages/api/hello.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
type Data = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>
|
||||
) {
|
||||
res.status(200).json({ name: 'John Doe' })
|
||||
}
|
||||
12
tailwind.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
"./public/**/*.html",
|
||||
],
|
||||
darkMode: "media",
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [require("daisyui")],
|
||||
};
|
||||
29
tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||