├── .eslintrc.json ├── .gitignore ├── README.md ├── components.json ├── next.config.mjs ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── public ├── next.svg └── vercel.svg ├── src ├── app │ ├── api │ │ ├── chat │ │ │ └── route.ts │ │ ├── ex1 │ │ │ └── route.ts │ │ ├── ex2 │ │ │ └── route.ts │ │ ├── ex3 │ │ │ └── route.ts │ │ └── ex4 │ │ │ └── route.ts │ ├── components │ │ └── chat.tsx │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── components │ └── ui │ │ ├── button.tsx │ │ └── input.tsx ├── data │ └── states.json └── lib │ └── utils.ts ├── tailwind.config.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build a RAG Application 2 | ## With LangChain & Next.js 3 | --- 4 | 5 | ### Author Links 6 | 7 | 👋 Hello, I'm Dave Gray. 8 | 9 | 📚 [My Courses](https://courses.davegray.codes/) 10 | 11 | ✅ [Check out my YouTube Channel with hundreds of tutorials](https://www.youtube.com/DaveGrayTeachesCode). 12 | 13 | 🚩 [Subscribe to my channel](https://bit.ly/3nGHmNn) 14 | 15 | 💖 [Support My Content](https://patreon.com/davegray) 16 | 17 | 🚀 Follow Me: 18 | 19 | - [Twitter](https://twitter.com/yesdavidgray) 20 | - [LinkedIn](https://www.linkedin.com/in/davidagray/) 21 | - [Blog](https://davegray.codes) 22 | 23 | --- 24 | 25 | ### Description 26 | 27 | 📺 [YouTube Video](https://youtu.be/YLagvzoWCL0) for this repository. 28 | 29 | --- 30 | 31 | ### ⚙ Usage 32 | 33 | - Provide your own .env.local file with an OpenAI API key 34 | - npm install 35 | - npm run dev 36 | 37 | --- 38 | 39 | ### 🎓 Academic Honesty 40 | 41 | **DO NOT COPY FOR AN ASSIGNMENT** - Avoid plagiarism and adhere to the spirit of this [Academic Honesty Policy](https://www.freecodecamp.org/news/academic-honesty-policy/). 42 | 43 | --- 44 | 45 | ### 📚 Tutorial References 46 | 47 | - 🔗 [LangChain JS/TS Docs](https://js.langchain.com/docs/get_started/introduction) 48 | - 🔗 [Next.js](https://nextjs.org/) 49 | - 🔗 [Vercel AI SDK](https://sdk.vercel.ai/docs) 50 | - 🔗 [OpenAI](https://openai.com/) 51 | - 🔗 [shadcn/ui](https://ui.shadcn.com/) 52 | - 🔗 [Next.js Light & Dark Modes](https://www.davegray.codes/posts/light-dark-mode-nextjs-app-router-tailwind) -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "stone", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-ai-prep", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@langchain/openai": "^0.0.28", 13 | "@radix-ui/react-slot": "^1.0.2", 14 | "ai": "^3.0.23", 15 | "class-variance-authority": "^0.7.0", 16 | "clsx": "^2.1.0", 17 | "langchain": "^0.1.36", 18 | "lucide-react": "^0.370.0", 19 | "next": "14.2.1", 20 | "openai": "^4.37.1", 21 | "react": "^18", 22 | "react-dom": "^18", 23 | "tailwind-merge": "^2.2.2", 24 | "tailwindcss-animate": "^1.0.7" 25 | }, 26 | "devDependencies": { 27 | "@types/node": "^20", 28 | "@types/react": "^18", 29 | "@types/react-dom": "^18", 30 | "eslint": "^8", 31 | "eslint-config-next": "14.2.1", 32 | "postcss": "^8", 33 | "tailwindcss": "^3.4.1", 34 | "typescript": "^5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/api/chat/route.ts: -------------------------------------------------------------------------------- 1 | import OpenAI from 'openai'; 2 | import { OpenAIStream, StreamingTextResponse } from 'ai'; 3 | 4 | export const dynamic = 'force-dynamic' 5 | 6 | const openai = new OpenAI({ 7 | apiKey: process.env.OPENAI_API_KEY!, 8 | }); 9 | 10 | export async function POST(req: Request) { 11 | // Extract the `messages` from the body of the request 12 | const { messages } = await req.json(); 13 | 14 | // Request the OpenAI API for the response based on the prompt 15 | const response = await openai.chat.completions.create({ 16 | model: 'gpt-3.5-turbo', 17 | stream: true, 18 | messages: messages, 19 | }); 20 | 21 | // Convert the response into a friendly text-stream 22 | const stream = OpenAIStream(response); 23 | 24 | // Respond with the stream 25 | return new StreamingTextResponse(stream); 26 | } -------------------------------------------------------------------------------- /src/app/api/ex1/route.ts: -------------------------------------------------------------------------------- 1 | import { 2 | StreamingTextResponse, 3 | createStreamDataTransformer 4 | } from 'ai'; 5 | import { ChatOpenAI } from '@langchain/openai'; 6 | import { PromptTemplate } from '@langchain/core/prompts'; 7 | import { HttpResponseOutputParser } from 'langchain/output_parsers'; 8 | 9 | export const dynamic = 'force-dynamic' 10 | 11 | export async function POST(req: Request) { 12 | try { 13 | // Extract the `messages` from the body of the request 14 | const { messages } = await req.json(); 15 | const message = messages.at(-1).content; 16 | 17 | const prompt = PromptTemplate.fromTemplate("{message}"); 18 | 19 | const model = new ChatOpenAI({ 20 | apiKey: process.env.OPENAI_API_KEY!, 21 | model: 'gpt-3.5-turbo', 22 | temperature: 0.8, 23 | }); 24 | 25 | /** 26 | * Chat models stream message chunks rather than bytes, so this 27 | * output parser handles serialization and encoding. 28 | */ 29 | const parser = new HttpResponseOutputParser(); 30 | 31 | const chain = prompt.pipe(model).pipe(parser); 32 | 33 | // Convert the response into a friendly text-stream 34 | const stream = await chain.stream({ message }); 35 | 36 | //const decoder = new TextDecoder() 37 | 38 | // Each chunk has the same interface as a chat message 39 | // for await (const chunk of stream) { 40 | // //console.log(chunk?.content); 41 | // if (chunk) { 42 | // console.log(decoder.decode(chunk)) 43 | // } 44 | // } 45 | 46 | // Respond with the stream 47 | return new StreamingTextResponse( 48 | stream.pipeThrough(createStreamDataTransformer()), 49 | ); 50 | } catch (e: any) { 51 | return Response.json({ error: e.message }, { status: e.status ?? 500 }); 52 | } 53 | } -------------------------------------------------------------------------------- /src/app/api/ex2/route.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Message as VercelChatMessage, 3 | StreamingTextResponse, 4 | createStreamDataTransformer 5 | } from 'ai'; 6 | import { ChatOpenAI } from '@langchain/openai'; 7 | import { PromptTemplate } from '@langchain/core/prompts'; 8 | import { HttpResponseOutputParser } from 'langchain/output_parsers'; 9 | 10 | export const dynamic = 'force-dynamic' 11 | 12 | /** 13 | * Basic memory formatter that stringifies and passes 14 | * message history directly into the model. 15 | */ 16 | const formatMessage = (message: VercelChatMessage) => { 17 | return `${message.role}: ${message.content}`; 18 | }; 19 | 20 | const TEMPLATE = `You are a comedian. You have witty replies to user questions and you tell jokes. 21 | 22 | Current conversation: 23 | {chat_history} 24 | 25 | user: {input} 26 | assistant:`; 27 | 28 | 29 | export async function POST(req: Request) { 30 | try { 31 | // Extract the `messages` from the body of the request 32 | const { messages } = await req.json(); 33 | 34 | const formattedPreviousMessages = messages.slice(0, -1).map(formatMessage); 35 | 36 | const currentMessageContent = messages.at(-1).content; 37 | 38 | const prompt = PromptTemplate.fromTemplate(TEMPLATE); 39 | 40 | const model = new ChatOpenAI({ 41 | apiKey: process.env.OPENAI_API_KEY!, 42 | model: 'gpt-3.5-turbo', 43 | temperature: 0.8, 44 | verbose: true, 45 | }); 46 | 47 | /** 48 | * Chat models stream message chunks rather than bytes, so this 49 | * output parser handles serialization and encoding. 50 | */ 51 | const parser = new HttpResponseOutputParser(); 52 | 53 | const chain = prompt.pipe(model.bind({ stop: ["?"] })).pipe(parser); 54 | 55 | // Convert the response into a friendly text-stream 56 | const stream = await chain.stream({ 57 | chat_history: formattedPreviousMessages.join('\n'), 58 | input: currentMessageContent, 59 | }); 60 | 61 | // Respond with the stream 62 | return new StreamingTextResponse( 63 | stream.pipeThrough(createStreamDataTransformer()), 64 | ); 65 | } catch (e: any) { 66 | return Response.json({ error: e.message }, { status: e.status ?? 500 }); 67 | } 68 | } -------------------------------------------------------------------------------- /src/app/api/ex3/route.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Message as VercelChatMessage, 3 | StreamingTextResponse, 4 | createStreamDataTransformer 5 | } from 'ai'; 6 | import { ChatOpenAI } from '@langchain/openai'; 7 | import { PromptTemplate } from '@langchain/core/prompts'; 8 | import { HttpResponseOutputParser } from 'langchain/output_parsers'; 9 | 10 | export const dynamic = 'force-dynamic' 11 | 12 | /** 13 | * Basic memory formatter that stringifies and passes 14 | * message history directly into the model. 15 | */ 16 | const formatMessage = (message: VercelChatMessage) => { 17 | return `${message.role}: ${message.content}`; 18 | }; 19 | 20 | const TEMPLATE = `You are a pirate named Patchy. All responses must be extremely verbose and in pirate dialect. 21 | 22 | Current conversation: 23 | {chat_history} 24 | 25 | user: {input} 26 | assistant:`; 27 | 28 | 29 | export async function POST(req: Request) { 30 | try { 31 | // Extract the `messages` from the body of the request 32 | const { messages } = await req.json(); 33 | 34 | const formattedPreviousMessages = messages.slice(0, -1).map(formatMessage); 35 | 36 | const currentMessageContent = messages.at(-1).content; 37 | 38 | const prompt = PromptTemplate.fromTemplate(TEMPLATE); 39 | 40 | const model = new ChatOpenAI({ 41 | apiKey: process.env.OPENAI_API_KEY!, 42 | model: 'gpt-3.5-turbo', 43 | temperature: 0.8, 44 | }); 45 | 46 | /** 47 | * Chat models stream message chunks rather than bytes, so this 48 | * output parser handles serialization and encoding. 49 | */ 50 | const parser = new HttpResponseOutputParser(); 51 | 52 | const chain = prompt.pipe(model).pipe(parser); 53 | 54 | // Convert the response into a friendly text-stream 55 | const stream = await chain.stream({ 56 | chat_history: formattedPreviousMessages.join('\n'), 57 | input: currentMessageContent, 58 | }); 59 | 60 | // Respond with the stream 61 | return new StreamingTextResponse( 62 | stream.pipeThrough(createStreamDataTransformer()), 63 | ); 64 | } catch (e: any) { 65 | return Response.json({ error: e.message }, { status: e.status ?? 500 }); 66 | } 67 | } -------------------------------------------------------------------------------- /src/app/api/ex4/route.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Message as VercelChatMessage, 3 | StreamingTextResponse, 4 | createStreamDataTransformer 5 | } from 'ai'; 6 | import { ChatOpenAI } from '@langchain/openai'; 7 | import { PromptTemplate } from '@langchain/core/prompts'; 8 | import { HttpResponseOutputParser } from 'langchain/output_parsers'; 9 | 10 | import { JSONLoader } from "langchain/document_loaders/fs/json"; 11 | import { RunnableSequence } from '@langchain/core/runnables' 12 | import { formatDocumentsAsString } from 'langchain/util/document'; 13 | import { CharacterTextSplitter } from 'langchain/text_splitter'; 14 | 15 | const loader = new JSONLoader( 16 | "src/data/states.json", 17 | ["/state", "/code", "/nickname", "/website", "/admission_date", "/admission_number", "/capital_city", "/capital_url", "/population", "/population_rank", "/constitution_url", "/twitter_url"], 18 | ); 19 | 20 | export const dynamic = 'force-dynamic' 21 | 22 | /** 23 | * Basic memory formatter that stringifies and passes 24 | * message history directly into the model. 25 | */ 26 | const formatMessage = (message: VercelChatMessage) => { 27 | return `${message.role}: ${message.content}`; 28 | }; 29 | 30 | const TEMPLATE = `Answer the user's questions based only on the following context. If the answer is not in the context, reply politely that you do not have that information available.: 31 | ============================== 32 | Context: {context} 33 | ============================== 34 | Current conversation: {chat_history} 35 | 36 | user: {question} 37 | assistant:`; 38 | 39 | 40 | export async function POST(req: Request) { 41 | try { 42 | // Extract the `messages` from the body of the request 43 | const { messages } = await req.json(); 44 | 45 | const formattedPreviousMessages = messages.slice(0, -1).map(formatMessage); 46 | 47 | const currentMessageContent = messages[messages.length - 1].content; 48 | 49 | const docs = await loader.load(); 50 | 51 | // load a JSON object 52 | // const textSplitter = new CharacterTextSplitter(); 53 | // const docs = await textSplitter.createDocuments([JSON.stringify({ 54 | // "state": "Kansas", 55 | // "slug": "kansas", 56 | // "code": "KS", 57 | // "nickname": "Sunflower State", 58 | // "website": "https://www.kansas.gov", 59 | // "admission_date": "1861-01-29", 60 | // "admission_number": 34, 61 | // "capital_city": "Topeka", 62 | // "capital_url": "http://www.topeka.org", 63 | // "population": 2893957, 64 | // "population_rank": 34, 65 | // "constitution_url": "https://kslib.info/405/Kansas-Constitution", 66 | // "twitter_url": "http://www.twitter.com/ksgovernment", 67 | // })]); 68 | 69 | const prompt = PromptTemplate.fromTemplate(TEMPLATE); 70 | 71 | const model = new ChatOpenAI({ 72 | apiKey: process.env.OPENAI_API_KEY!, 73 | model: 'gpt-3.5-turbo', 74 | temperature: 0, 75 | streaming: true, 76 | verbose: true, 77 | }); 78 | 79 | /** 80 | * Chat models stream message chunks rather than bytes, so this 81 | * output parser handles serialization and encoding. 82 | */ 83 | const parser = new HttpResponseOutputParser(); 84 | 85 | const chain = RunnableSequence.from([ 86 | { 87 | question: (input) => input.question, 88 | chat_history: (input) => input.chat_history, 89 | context: () => formatDocumentsAsString(docs), 90 | }, 91 | prompt, 92 | model, 93 | parser, 94 | ]); 95 | 96 | // Convert the response into a friendly text-stream 97 | const stream = await chain.stream({ 98 | chat_history: formattedPreviousMessages.join('\n'), 99 | question: currentMessageContent, 100 | }); 101 | 102 | // Respond with the stream 103 | return new StreamingTextResponse( 104 | stream.pipeThrough(createStreamDataTransformer()), 105 | ); 106 | } catch (e: any) { 107 | return Response.json({ error: e.message }, { status: e.status ?? 500 }); 108 | } 109 | } -------------------------------------------------------------------------------- /src/app/components/chat.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { Input } from "@/components/ui/input" 4 | import { Button } from "@/components/ui/button" 5 | import { useChat } from "ai/react" 6 | import { useRef, useEffect } from 'react' 7 | 8 | export function Chat() { 9 | 10 | const { messages, input, handleInputChange, handleSubmit } = useChat({ 11 | api: 'api/ex4', 12 | onError: (e) => { 13 | console.log(e) 14 | } 15 | }) 16 | const chatParent = useRef(null) 17 | 18 | useEffect(() => { 19 | const domNode = chatParent.current 20 | if (domNode) { 21 | domNode.scrollTop = domNode.scrollHeight 22 | } 23 | }) 24 | 25 | return ( 26 |
27 | 28 |
29 |

LangChain Chat

30 |
31 | 32 |
33 |
34 | 35 | 38 |
39 |
40 | 41 |
42 |
    43 | {messages.map((m, index) => ( 44 |
    45 | {m.role === 'user' ? ( 46 |
  • 47 |
    48 |

    {m.content}

    49 |
    50 |
  • 51 | ) : ( 52 |
  • 53 |
    54 |

    {m.content}

    55 |
    56 |
  • 57 | )} 58 |
    59 | ))} 60 |
61 |
62 |
63 | ) 64 | } 65 | -------------------------------------------------------------------------------- /src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitdagray/nextjs-rag-langchain/22f9da64fbb0e8fc64cf1da4389046b21de599d2/src/app/favicon.ico -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --background: 0 0% 100%; 8 | --foreground: 20 14.3% 4.1%; 9 | --card: 0 0% 100%; 10 | --card-foreground: 20 14.3% 4.1%; 11 | --popover: 0 0% 100%; 12 | --popover-foreground: 20 14.3% 4.1%; 13 | --primary: 24 9.8% 10%; 14 | --primary-foreground: 60 9.1% 97.8%; 15 | --secondary: 60 4.8% 95.9%; 16 | --secondary-foreground: 24 9.8% 10%; 17 | --muted: 60 4.8% 95.9%; 18 | --muted-foreground: 25 5.3% 44.7%; 19 | --accent: 60 4.8% 95.9%; 20 | --accent-foreground: 24 9.8% 10%; 21 | --destructive: 0 84.2% 60.2%; 22 | --destructive-foreground: 60 9.1% 97.8%; 23 | --border: 20 5.9% 90%; 24 | --input: 20 5.9% 90%; 25 | --ring: 20 14.3% 4.1%; 26 | --radius: 0.5rem; 27 | } 28 | 29 | .dark { 30 | --background: 20 14.3% 4.1%; 31 | --foreground: 60 9.1% 97.8%; 32 | --card: 20 14.3% 4.1%; 33 | --card-foreground: 60 9.1% 97.8%; 34 | --popover: 20 14.3% 4.1%; 35 | --popover-foreground: 60 9.1% 97.8%; 36 | --primary: 60 9.1% 97.8%; 37 | --primary-foreground: 24 9.8% 10%; 38 | --secondary: 12 6.5% 15.1%; 39 | --secondary-foreground: 60 9.1% 97.8%; 40 | --muted: 12 6.5% 15.1%; 41 | --muted-foreground: 24 5.4% 63.9%; 42 | --accent: 12 6.5% 15.1%; 43 | --accent-foreground: 60 9.1% 97.8%; 44 | --destructive: 0 62.8% 30.6%; 45 | --destructive-foreground: 60 9.1% 97.8%; 46 | --border: 12 6.5% 15.1%; 47 | --input: 12 6.5% 15.1%; 48 | --ring: 24 5.7% 82.9%; 49 | } 50 | } 51 | 52 | 53 | @layer base { 54 | * { 55 | @apply border-border; 56 | } 57 | 58 | body { 59 | @apply bg-background text-foreground; 60 | } 61 | } -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Chat } from "./components/chat"; 2 | 3 | export const runtime = 'edge'; 4 | 5 | export default function Page() { 6 | return ; 7 | } -------------------------------------------------------------------------------- /src/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | } 34 | ) 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button" 45 | return ( 46 | 51 | ) 52 | } 53 | ) 54 | Button.displayName = "Button" 55 | 56 | export { Button, buttonVariants } 57 | -------------------------------------------------------------------------------- /src/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes {} 7 | 8 | const Input = React.forwardRef( 9 | ({ className, type, ...props }, ref) => { 10 | return ( 11 | 20 | ) 21 | } 22 | ) 23 | Input.displayName = "Input" 24 | 25 | export { Input } 26 | -------------------------------------------------------------------------------- /src/data/states.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "state": "Alabama", 4 | "slug": "alabama", 5 | "code": "AL", 6 | "nickname": "Yellowhammer State", 7 | "website": "http://www.alabama.gov", 8 | "admission_date": "1819-12-14", 9 | "admission_number": 22, 10 | "capital_city": "Montgomery", 11 | "capital_url": "http://www.montgomeryal.gov", 12 | "population": 4833722, 13 | "population_rank": 23, 14 | "constitution_url": "http://alisondb.legislature.state.al.us/alison/default.aspx", 15 | "state_flag_url": "https://cdn.civil.services/us-states/flags/alabama-large.png", 16 | "state_seal_url": "https://cdn.civil.services/us-states/seals/alabama-large.png", 17 | "map_image_url": "https://cdn.civil.services/us-states/maps/alabama-large.png", 18 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/alabama.jpg", 19 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/alabama.jpg", 20 | "twitter_url": "https://twitter.com/alabamagov", 21 | "facebook_url": "https://www.facebook.com/alabamagov" 22 | }, 23 | { 24 | "state": "Alaska", 25 | "slug": "alaska", 26 | "code": "AK", 27 | "nickname": "The Last Frontier", 28 | "website": "http://alaska.gov", 29 | "admission_date": "1959-01-03", 30 | "admission_number": 49, 31 | "capital_city": "Juneau", 32 | "capital_url": "http://www.juneau.org", 33 | "population": 735132, 34 | "population_rank": 47, 35 | "constitution_url": "http://www.legis.state.ak.us/basis/folioproxy.asp?url=http://wwwjnu01.legis.state.ak.us/cgi-bin/folioisa.dll/acontxt/query=*/doc/{t1}?", 36 | "state_flag_url": "https://cdn.civil.services/us-states/flags/alaska-large.png", 37 | "state_seal_url": "https://cdn.civil.services/us-states/seals/alaska-large.png", 38 | "map_image_url": "https://cdn.civil.services/us-states/maps/alaska-large.png", 39 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/alaska.jpg", 40 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/alaska.jpg", 41 | "twitter_url": "https://twitter.com/alaska", 42 | "facebook_url": "https://www.facebook.com/AlaskaLocalGovernments" 43 | }, 44 | { 45 | "state": "Arizona", 46 | "slug": "arizona", 47 | "code": "AZ", 48 | "nickname": "The Grand Canyon State", 49 | "website": "https://az.gov", 50 | "admission_date": "1912-02-14", 51 | "admission_number": 48, 52 | "capital_city": "Phoenix", 53 | "capital_url": "https://www.phoenix.gov", 54 | "population": 6626624, 55 | "population_rank": 15, 56 | "constitution_url": "http://www.azleg.gov/Constitution.asp", 57 | "state_flag_url": "https://cdn.civil.services/us-states/flags/arizona-large.png", 58 | "state_seal_url": "https://cdn.civil.services/us-states/seals/arizona-large.png", 59 | "map_image_url": "https://cdn.civil.services/us-states/maps/arizona-large.png", 60 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/arizona.jpg", 61 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/arizona.jpg", 62 | "twitter_url": null, 63 | "facebook_url": null 64 | }, 65 | { 66 | "state": "Arkansas", 67 | "slug": "arkansas", 68 | "code": "AR", 69 | "nickname": "The Natural State", 70 | "website": "http://arkansas.gov", 71 | "admission_date": "1836-06-15", 72 | "admission_number": 25, 73 | "capital_city": "Little Rock", 74 | "capital_url": "http://www.littlerock.org", 75 | "population": 2959373, 76 | "population_rank": 32, 77 | "constitution_url": "http://www.arkleg.state.ar.us/assembly/Summary/ArkansasConstitution1874.pdf", 78 | "state_flag_url": "https://cdn.civil.services/us-states/flags/arkansas-large.png", 79 | "state_seal_url": "https://cdn.civil.services/us-states/seals/arkansas-large.png", 80 | "map_image_url": "https://cdn.civil.services/us-states/maps/arkansas-large.png", 81 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/arkansas.jpg", 82 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/arkansas.jpg", 83 | "twitter_url": "https://twitter.com/arkansasgov", 84 | "facebook_url": "https://www.facebook.com/Arkansas.gov" 85 | }, 86 | { 87 | "state": "California", 88 | "slug": "california", 89 | "code": "CA", 90 | "nickname": "Golden State", 91 | "website": "http://www.ca.gov", 92 | "admission_date": "1850-09-09", 93 | "admission_number": 31, 94 | "capital_city": "Sacramento", 95 | "capital_url": "http://www.cityofsacramento.org", 96 | "population": 38332521, 97 | "population_rank": 1, 98 | "constitution_url": "http://www.leginfo.ca.gov/const-toc.html", 99 | "state_flag_url": "https://cdn.civil.services/us-states/flags/california-large.png", 100 | "state_seal_url": "https://cdn.civil.services/us-states/seals/california-large.png", 101 | "map_image_url": "https://cdn.civil.services/us-states/maps/california-large.png", 102 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/california.jpg", 103 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/california.jpg", 104 | "twitter_url": "https://twitter.com/cagovernment", 105 | "facebook_url": null 106 | }, 107 | { 108 | "state": "Colorado", 109 | "slug": "colorado", 110 | "code": "CO", 111 | "nickname": "The Centennial State", 112 | "website": "https://www.colorado.gov", 113 | "admission_date": "1876-08-01", 114 | "admission_number": 38, 115 | "capital_city": "Denver", 116 | "capital_url": "http://www.denvergov.org", 117 | "population": 5268367, 118 | "population_rank": 22, 119 | "constitution_url": "https://www.colorado.gov/pacific/archives/government", 120 | "state_flag_url": "https://cdn.civil.services/us-states/flags/colorado-large.png", 121 | "state_seal_url": "https://cdn.civil.services/us-states/seals/colorado-large.png", 122 | "map_image_url": "https://cdn.civil.services/us-states/maps/colorado-large.png", 123 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/colorado.jpg", 124 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/colorado.jpg", 125 | "twitter_url": "https://twitter.com/coloradogov", 126 | "facebook_url": "https://www.facebook.com/Colorado.gov" 127 | }, 128 | { 129 | "state": "Connecticut", 130 | "slug": "connecticut", 131 | "code": "CT", 132 | "nickname": "Constitution State", 133 | "website": "http://www.ct.gov", 134 | "admission_date": "1788-01-09", 135 | "admission_number": 5, 136 | "capital_city": "Hartford", 137 | "capital_url": "http://www.hartford.gov", 138 | "population": 3596080, 139 | "population_rank": 29, 140 | "constitution_url": "http://www.ct.gov/sots/cwp/view.asp?a=3188&q=392288", 141 | "state_flag_url": "https://cdn.civil.services/us-states/flags/connecticut-large.png", 142 | "state_seal_url": "https://cdn.civil.services/us-states/seals/connecticut-large.png", 143 | "map_image_url": "https://cdn.civil.services/us-states/maps/connecticut-large.png", 144 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/connecticut.jpg", 145 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/connecticut.jpg", 146 | "twitter_url": null, 147 | "facebook_url": null 148 | }, 149 | { 150 | "state": "Delaware", 151 | "slug": "delaware", 152 | "code": "DE", 153 | "nickname": "The First State / The Diamond State", 154 | "website": "http://delaware.gov", 155 | "admission_date": "1787-12-07", 156 | "admission_number": 1, 157 | "capital_city": "Dover", 158 | "capital_url": "http://www.cityofdover.com", 159 | "population": 925749, 160 | "population_rank": 45, 161 | "constitution_url": "http://www.state.de.us/facts/constit/welcome.htm", 162 | "state_flag_url": "https://cdn.civil.services/us-states/flags/delaware-large.png", 163 | "state_seal_url": "https://cdn.civil.services/us-states/seals/delaware-large.png", 164 | "map_image_url": "https://cdn.civil.services/us-states/maps/delaware-large.png", 165 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/delaware.jpg", 166 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/delaware.jpg", 167 | "twitter_url": "https://twitter.com/delaware_gov", 168 | "facebook_url": "https://www.facebook.com/delaware.gov" 169 | }, 170 | { 171 | "state": "Florida", 172 | "slug": "florida", 173 | "code": "FL", 174 | "nickname": "Sunshine State", 175 | "website": "http://www.myflorida.com", 176 | "admission_date": "1845-03-03", 177 | "admission_number": 27, 178 | "capital_city": "Tallahassee", 179 | "capital_url": "https://www.talgov.com/Main/Home.aspx", 180 | "population": 19552860, 181 | "population_rank": 4, 182 | "constitution_url": "http://www.leg.state.fl.us/Statutes/index.cfm", 183 | "state_flag_url": "https://cdn.civil.services/us-states/flags/florida-large.png", 184 | "state_seal_url": "https://cdn.civil.services/us-states/seals/florida-large.png", 185 | "map_image_url": "https://cdn.civil.services/us-states/maps/florida-large.png", 186 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/florida.jpg", 187 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/florida.jpg", 188 | "twitter_url": null, 189 | "facebook_url": null 190 | }, 191 | { 192 | "state": "Georgia", 193 | "slug": "georgia", 194 | "code": "GA", 195 | "nickname": "Peach State", 196 | "website": "http://georgia.gov", 197 | "admission_date": "1788-01-02", 198 | "admission_number": 4, 199 | "capital_city": "Atlanta", 200 | "capital_url": "http://www.atlantaga.gov", 201 | "population": 9992167, 202 | "population_rank": 8, 203 | "constitution_url": "http://sos.ga.gov/admin/files/Constitution_2013_Final_Printed.pdf", 204 | "state_flag_url": "https://cdn.civil.services/us-states/flags/georgia-large.png", 205 | "state_seal_url": "https://cdn.civil.services/us-states/seals/georgia-large.png", 206 | "map_image_url": "https://cdn.civil.services/us-states/maps/georgia-large.png", 207 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/georgia.jpg", 208 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/georgia.jpg", 209 | "twitter_url": "http://twitter.com/georgiagov", 210 | "facebook_url": "http://www.facebook.com/pages/georgiagov/29760668054" 211 | }, 212 | { 213 | "state": "Hawaii", 214 | "slug": "hawaii", 215 | "code": "HI", 216 | "nickname": "Aloha State", 217 | "website": "https://www.ehawaii.gov", 218 | "admission_date": "1959-08-21", 219 | "admission_number": 50, 220 | "capital_city": "Honolulu", 221 | "capital_url": "http://www.co.honolulu.hi.us", 222 | "population": 1404054, 223 | "population_rank": 40, 224 | "constitution_url": "http://lrbhawaii.org/con", 225 | "state_flag_url": "https://cdn.civil.services/us-states/flags/hawaii-large.png", 226 | "state_seal_url": "https://cdn.civil.services/us-states/seals/hawaii-large.png", 227 | "map_image_url": "https://cdn.civil.services/us-states/maps/hawaii-large.png", 228 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/hawaii.jpg", 229 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/hawaii.jpg", 230 | "twitter_url": "https://twitter.com/ehawaiigov", 231 | "facebook_url": "https://www.facebook.com/ehawaii.gov" 232 | }, 233 | { 234 | "state": "Idaho", 235 | "slug": "idaho", 236 | "code": "ID", 237 | "nickname": "Gem State", 238 | "website": "https://www.idaho.gov", 239 | "admission_date": "1890-07-03", 240 | "admission_number": 43, 241 | "capital_city": "Boise", 242 | "capital_url": "http://www.cityofboise.org", 243 | "population": 1612136, 244 | "population_rank": 39, 245 | "constitution_url": "http://www.legislature.idaho.gov/idstat/IC/Title003.htm", 246 | "state_flag_url": "https://cdn.civil.services/us-states/flags/idaho-large.png", 247 | "state_seal_url": "https://cdn.civil.services/us-states/seals/idaho-large.png", 248 | "map_image_url": "https://cdn.civil.services/us-states/maps/idaho-large.png", 249 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/idaho.jpg", 250 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/idaho.jpg", 251 | "twitter_url": "https://twitter.com/IDAHOgov", 252 | "facebook_url": null 253 | }, 254 | { 255 | "state": "Illinois", 256 | "slug": "illinois", 257 | "code": "IL", 258 | "nickname": "Prairie State", 259 | "website": "https://www.illinois.gov", 260 | "admission_date": "1818-12-03", 261 | "admission_number": 21, 262 | "capital_city": "Springfield", 263 | "capital_url": "http://www.springfield.il.us", 264 | "population": 12882135, 265 | "population_rank": 5, 266 | "constitution_url": "http://www.ilga.gov/commission/lrb/conmain.htm", 267 | "state_flag_url": "https://cdn.civil.services/us-states/flags/illinois-large.png", 268 | "state_seal_url": "https://cdn.civil.services/us-states/seals/illinois-large.png", 269 | "map_image_url": "https://cdn.civil.services/us-states/maps/illinois-large.png", 270 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/illinois.jpg", 271 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/illinois.jpg", 272 | "twitter_url": null, 273 | "facebook_url": null 274 | }, 275 | { 276 | "state": "Indiana", 277 | "slug": "indiana", 278 | "code": "IN", 279 | "nickname": "Hoosier State", 280 | "website": "http://www.in.gov", 281 | "admission_date": "1816-12-11", 282 | "admission_number": 19, 283 | "capital_city": "Indianapolis", 284 | "capital_url": "http://www.indy.gov/Pages/Home.aspx", 285 | "population": 6570902, 286 | "population_rank": 16, 287 | "constitution_url": "http://www.law.indiana.edu/uslawdocs/inconst.html", 288 | "state_flag_url": "https://cdn.civil.services/us-states/flags/indiana-large.png", 289 | "state_seal_url": "https://cdn.civil.services/us-states/seals/indiana-large.png", 290 | "map_image_url": "https://cdn.civil.services/us-states/maps/indiana-large.png", 291 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/indiana.jpg", 292 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/indiana.jpg", 293 | "twitter_url": "https://twitter.com/in_gov", 294 | "facebook_url": "https://www.facebook.com/IndianaGovernment" 295 | }, 296 | { 297 | "state": "Iowa", 298 | "slug": "iowa", 299 | "code": "IA", 300 | "nickname": "Hawkeye State", 301 | "website": "https://www.iowa.gov", 302 | "admission_date": "1846-12-28", 303 | "admission_number": 29, 304 | "capital_city": "Des Moines", 305 | "capital_url": "http://www.ci.des-moines.ia.us", 306 | "population": 3090416, 307 | "population_rank": 30, 308 | "constitution_url": "http://publications.iowa.gov/135/1/history/7-7.html", 309 | "state_flag_url": "https://cdn.civil.services/us-states/flags/iowa-large.png", 310 | "state_seal_url": "https://cdn.civil.services/us-states/seals/iowa-large.png", 311 | "map_image_url": "https://cdn.civil.services/us-states/maps/iowa-large.png", 312 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/iowa.jpg", 313 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/iowa.jpg", 314 | "twitter_url": "https://twitter.com/IAGOVTWEETS", 315 | "facebook_url": null 316 | }, 317 | { 318 | "state": "Kansas", 319 | "slug": "kansas", 320 | "code": "KS", 321 | "nickname": "Sunflower State", 322 | "website": "https://www.kansas.gov", 323 | "admission_date": "1861-01-29", 324 | "admission_number": 34, 325 | "capital_city": "Topeka", 326 | "capital_url": "http://www.topeka.org", 327 | "population": 2893957, 328 | "population_rank": 34, 329 | "constitution_url": "https://kslib.info/405/Kansas-Constitution", 330 | "state_flag_url": "https://cdn.civil.services/us-states/flags/kansas-large.png", 331 | "state_seal_url": "https://cdn.civil.services/us-states/seals/kansas-large.png", 332 | "map_image_url": "https://cdn.civil.services/us-states/maps/kansas-large.png", 333 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/kansas.jpg", 334 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/kansas.jpg", 335 | "twitter_url": "http://www.twitter.com/ksgovernment", 336 | "facebook_url": "http://www.facebook.com/pages/Topeka-KS/Kansasgov-Kansas-Government-Online/52068474220" 337 | }, 338 | { 339 | "state": "Kentucky", 340 | "slug": "kentucky", 341 | "code": "KY", 342 | "nickname": "Bluegrass State", 343 | "website": "http://kentucky.gov", 344 | "admission_date": "1792-06-01", 345 | "admission_number": 15, 346 | "capital_city": "Frankfort", 347 | "capital_url": "http://frankfort.ky.gov", 348 | "population": 4395295, 349 | "population_rank": 26, 350 | "constitution_url": "http://www.lrc.state.ky.us/Legresou/Constitu/intro.htm", 351 | "state_flag_url": "https://cdn.civil.services/us-states/flags/kentucky-large.png", 352 | "state_seal_url": "https://cdn.civil.services/us-states/seals/kentucky-large.png", 353 | "map_image_url": "https://cdn.civil.services/us-states/maps/kentucky-large.png", 354 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/kentucky.jpg", 355 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/kentucky.jpg", 356 | "twitter_url": "https://twitter.com/kygov", 357 | "facebook_url": "https://www.facebook.com/kygov" 358 | }, 359 | { 360 | "state": "Louisiana", 361 | "slug": "louisiana", 362 | "code": "LA", 363 | "nickname": "Pelican State", 364 | "website": "http://louisiana.gov", 365 | "admission_date": "1812-04-30", 366 | "admission_number": 18, 367 | "capital_city": "Baton Rouge", 368 | "capital_url": "http://brgov.com", 369 | "population": 4625470, 370 | "population_rank": 25, 371 | "constitution_url": "http://senate.legis.state.la.us/Documents/Constitution", 372 | "state_flag_url": "https://cdn.civil.services/us-states/flags/louisiana-large.png", 373 | "state_seal_url": "https://cdn.civil.services/us-states/seals/louisiana-large.png", 374 | "map_image_url": "https://cdn.civil.services/us-states/maps/louisiana-large.png", 375 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/louisiana.jpg", 376 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/louisiana.jpg", 377 | "twitter_url": null, 378 | "facebook_url": null 379 | }, 380 | { 381 | "state": "Maine", 382 | "slug": "maine", 383 | "code": "ME", 384 | "nickname": "Pine Tree State", 385 | "website": "http://www.maine.gov", 386 | "admission_date": "1820-03-15", 387 | "admission_number": 23, 388 | "capital_city": "Augusta", 389 | "capital_url": "http://www.augustamaine.gov", 390 | "population": 1328302, 391 | "population_rank": 41, 392 | "constitution_url": "http://www.maine.gov/legis/const", 393 | "state_flag_url": "https://cdn.civil.services/us-states/flags/maine-large.png", 394 | "state_seal_url": "https://cdn.civil.services/us-states/seals/maine-large.png", 395 | "map_image_url": "https://cdn.civil.services/us-states/maps/maine-large.png", 396 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/maine.jpg", 397 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/maine.jpg", 398 | "twitter_url": "https://twitter.com/mainegov_news", 399 | "facebook_url": "http://www.facebook.com/pages/Augusta-ME/Mainegov/98519328240" 400 | }, 401 | { 402 | "state": "Maryland", 403 | "slug": "maryland", 404 | "code": "MD", 405 | "nickname": "Old Line State", 406 | "website": "http://www.maryland.gov", 407 | "admission_date": "1788-04-28", 408 | "admission_number": 7, 409 | "capital_city": "Annapolis", 410 | "capital_url": "http://www.annapolis.gov", 411 | "population": 5928814, 412 | "population_rank": 19, 413 | "constitution_url": "http://msa.maryland.gov/msa/mdmanual/43const/html/const.html", 414 | "state_flag_url": "https://cdn.civil.services/us-states/flags/maryland-large.png", 415 | "state_seal_url": "https://cdn.civil.services/us-states/seals/maryland-large.png", 416 | "map_image_url": "https://cdn.civil.services/us-states/maps/maryland-large.png", 417 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/maryland.jpg", 418 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/maryland.jpg", 419 | "twitter_url": "https://twitter.com/statemaryland", 420 | "facebook_url": "https://www.facebook.com/statemaryland" 421 | }, 422 | { 423 | "state": "Massachusetts", 424 | "slug": "massachusetts", 425 | "code": "MA", 426 | "nickname": "Bay State", 427 | "website": "http://www.mass.gov", 428 | "admission_date": "1788-02-06", 429 | "admission_number": 6, 430 | "capital_city": "Boston", 431 | "capital_url": "http://www.ci.boston.ma.us", 432 | "population": 6692824, 433 | "population_rank": 14, 434 | "constitution_url": "http://www.state.ma.us/legis/const.htm", 435 | "state_flag_url": "https://cdn.civil.services/us-states/flags/massachusetts-large.png", 436 | "state_seal_url": "https://cdn.civil.services/us-states/seals/massachusetts-large.png", 437 | "map_image_url": "https://cdn.civil.services/us-states/maps/massachusetts-large.png", 438 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/massachusetts.jpg", 439 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/massachusetts.jpg", 440 | "twitter_url": "http://twitter.com/massgov", 441 | "facebook_url": "https://www.facebook.com/massgov" 442 | }, 443 | { 444 | "state": "Michigan", 445 | "slug": "michigan", 446 | "code": "MI", 447 | "nickname": "Wolverine State / Great Lakes State", 448 | "website": "http://www.michigan.gov", 449 | "admission_date": "1837-01-26", 450 | "admission_number": 26, 451 | "capital_city": "Lansing", 452 | "capital_url": "http://cityoflansingmi.com", 453 | "population": 9895622, 454 | "population_rank": 9, 455 | "constitution_url": "http://www.legislature.mi.gov/(S(hrowl12tg05hemnnkidim1jb))/mileg.aspx?page=GetObject&objectname=mcl-Constitution", 456 | "state_flag_url": "https://cdn.civil.services/us-states/flags/michigan-large.png", 457 | "state_seal_url": "https://cdn.civil.services/us-states/seals/michigan-large.png", 458 | "map_image_url": "https://cdn.civil.services/us-states/maps/michigan-large.png", 459 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/michigan.jpg", 460 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/michigan.jpg", 461 | "twitter_url": "https://twitter.com/migov", 462 | "facebook_url": "https://www.facebook.com/MIgovernment" 463 | }, 464 | { 465 | "state": "Minnesota", 466 | "slug": "minnesota", 467 | "code": "MN", 468 | "nickname": "North Star State / Land of 10,000 Lakes", 469 | "website": "https://mn.gov", 470 | "admission_date": "1858-05-11", 471 | "admission_number": 32, 472 | "capital_city": "Saint Paul", 473 | "capital_url": "http://www.stpaul.gov", 474 | "population": 5420380, 475 | "population_rank": 21, 476 | "constitution_url": "http://www.house.leg.state.mn.us/cco/rules/mncon/preamble.htm", 477 | "state_flag_url": "https://cdn.civil.services/us-states/flags/minnesota-large.png", 478 | "state_seal_url": "https://cdn.civil.services/us-states/seals/minnesota-large.png", 479 | "map_image_url": "https://cdn.civil.services/us-states/maps/minnesota-large.png", 480 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/minnesota.jpg", 481 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/minnesota.jpg", 482 | "twitter_url": null, 483 | "facebook_url": null 484 | }, 485 | { 486 | "state": "Mississippi", 487 | "slug": "mississippi", 488 | "code": "MS", 489 | "nickname": "Magnolia State", 490 | "website": "http://www.ms.gov", 491 | "admission_date": "1817-12-10", 492 | "admission_number": 20, 493 | "capital_city": "Jackson", 494 | "capital_url": "http://www.city.jackson.ms.us", 495 | "population": 2991207, 496 | "population_rank": 31, 497 | "constitution_url": "http://law.justia.com/constitution/mississippi", 498 | "state_flag_url": "https://cdn.civil.services/us-states/flags/mississippi-large.png", 499 | "state_seal_url": "https://cdn.civil.services/us-states/seals/mississippi-large.png", 500 | "map_image_url": "https://cdn.civil.services/us-states/maps/mississippi-large.png", 501 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/mississippi.jpg", 502 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/mississippi.jpg", 503 | "twitter_url": "https://twitter.com/msdotgov", 504 | "facebook_url": "https://www.facebook.com/msdotgov" 505 | }, 506 | { 507 | "state": "Missouri", 508 | "slug": "missouri", 509 | "code": "MO", 510 | "nickname": "Show Me State", 511 | "website": "https://www.mo.gov", 512 | "admission_date": "1821-08-10", 513 | "admission_number": 24, 514 | "capital_city": "Jefferson City", 515 | "capital_url": "http://www.jeffcitymo.org", 516 | "population": 6044171, 517 | "population_rank": 18, 518 | "constitution_url": "http://www.moga.mo.gov/mostatutes/moconstn.html", 519 | "state_flag_url": "https://cdn.civil.services/us-states/flags/missouri-large.png", 520 | "state_seal_url": "https://cdn.civil.services/us-states/seals/missouri-large.png", 521 | "map_image_url": "https://cdn.civil.services/us-states/maps/missouri-large.png", 522 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/missouri.jpg", 523 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/missouri.jpg", 524 | "twitter_url": "https://twitter.com/MoGov", 525 | "facebook_url": "https://www.facebook.com/mogov" 526 | }, 527 | { 528 | "state": "Montana", 529 | "slug": "montana", 530 | "code": "MT", 531 | "nickname": "Treasure State", 532 | "website": "http://mt.gov", 533 | "admission_date": "1889-11-08", 534 | "admission_number": 41, 535 | "capital_city": "Helena", 536 | "capital_url": "http://www.ci.helena.mt.us", 537 | "population": 1015165, 538 | "population_rank": 44, 539 | "constitution_url": "http://courts.mt.gov/content/library/docs/72constit.pdf", 540 | "state_flag_url": "https://cdn.civil.services/us-states/flags/montana-large.png", 541 | "state_seal_url": "https://cdn.civil.services/us-states/seals/montana-large.png", 542 | "map_image_url": "https://cdn.civil.services/us-states/maps/montana-large.png", 543 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/montana.jpg", 544 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/montana.jpg", 545 | "twitter_url": null, 546 | "facebook_url": null 547 | }, 548 | { 549 | "state": "Nebraska", 550 | "slug": "nebraska", 551 | "code": "NE", 552 | "nickname": "Cornhusker State", 553 | "website": "http://www.nebraska.gov", 554 | "admission_date": "1867-03-01", 555 | "admission_number": 37, 556 | "capital_city": "Lincoln", 557 | "capital_url": "http://lincoln.ne.gov", 558 | "population": 1868516, 559 | "population_rank": 37, 560 | "constitution_url": "http://www.state.ne.us/legislative/statutes/C", 561 | "state_flag_url": "https://cdn.civil.services/us-states/flags/nebraska-large.png", 562 | "state_seal_url": "https://cdn.civil.services/us-states/seals/nebraska-large.png", 563 | "map_image_url": "https://cdn.civil.services/us-states/maps/nebraska-large.png", 564 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/nebraska.jpg", 565 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/nebraska.jpg", 566 | "twitter_url": "https://twitter.com/Nebraskagov", 567 | "facebook_url": "https://www.facebook.com/nebraska.gov" 568 | }, 569 | { 570 | "state": "Nevada", 571 | "slug": "nevada", 572 | "code": "NV", 573 | "nickname": "The Silver State", 574 | "website": "http://nv.gov", 575 | "admission_date": "1864-10-31", 576 | "admission_number": 36, 577 | "capital_city": "Carson City", 578 | "capital_url": "http://www.carson.org", 579 | "population": 2790136, 580 | "population_rank": 35, 581 | "constitution_url": "http://www.leg.state.nv.us/Const/NvConst.html", 582 | "state_flag_url": "https://cdn.civil.services/us-states/flags/nevada-large.png", 583 | "state_seal_url": "https://cdn.civil.services/us-states/seals/nevada-large.png", 584 | "map_image_url": "https://cdn.civil.services/us-states/maps/nevada-large.png", 585 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/nevada.jpg", 586 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/nevada.jpg", 587 | "twitter_url": null, 588 | "facebook_url": null 589 | }, 590 | { 591 | "state": "New Hampshire", 592 | "slug": "new-hampshire", 593 | "code": "NH", 594 | "nickname": "Granite State", 595 | "website": "https://www.nh.gov", 596 | "admission_date": "1788-06-21", 597 | "admission_number": 9, 598 | "capital_city": "Concord", 599 | "capital_url": "http://www.concordnh.gov", 600 | "population": 1323459, 601 | "population_rank": 42, 602 | "constitution_url": "http://www.state.nh.us/constitution/constitution.html", 603 | "state_flag_url": "https://cdn.civil.services/us-states/flags/new-hampshire-large.png", 604 | "state_seal_url": "https://cdn.civil.services/us-states/seals/new-hampshire-large.png", 605 | "map_image_url": "https://cdn.civil.services/us-states/maps/new-hampshire-large.png", 606 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/new-hampshire.jpg", 607 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/new-hampshire.jpg", 608 | "twitter_url": "https://twitter.com/nhgov", 609 | "facebook_url": null 610 | }, 611 | { 612 | "state": "New Jersey", 613 | "slug": "new-jersey", 614 | "code": "NJ", 615 | "nickname": "Garden State", 616 | "website": "http://www.state.nj.us", 617 | "admission_date": "1787-12-18", 618 | "admission_number": 3, 619 | "capital_city": "Trenton", 620 | "capital_url": "http://www.trentonnj.org", 621 | "population": 8899339, 622 | "population_rank": 11, 623 | "constitution_url": "http://www.njleg.state.nj.us/lawsconstitution/consearch.asp", 624 | "state_flag_url": "https://cdn.civil.services/us-states/flags/new-jersey-large.png", 625 | "state_seal_url": "https://cdn.civil.services/us-states/seals/new-jersey-large.png", 626 | "map_image_url": "https://cdn.civil.services/us-states/maps/new-jersey-large.png", 627 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/new-jersey.jpg", 628 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/new-jersey.jpg", 629 | "twitter_url": null, 630 | "facebook_url": null 631 | }, 632 | { 633 | "state": "New Mexico", 634 | "slug": "new-mexico", 635 | "code": "NM", 636 | "nickname": "Land of Enchantment", 637 | "website": "http://www.newmexico.gov", 638 | "admission_date": "1912-01-06", 639 | "admission_number": 47, 640 | "capital_city": "Santa Fe", 641 | "capital_url": "http://www.santafenm.gov", 642 | "population": 2085287, 643 | "population_rank": 36, 644 | "constitution_url": "http://www.loc.gov/law/guide/us-nm.html", 645 | "state_flag_url": "https://cdn.civil.services/us-states/flags/new-mexico-large.png", 646 | "state_seal_url": "https://cdn.civil.services/us-states/seals/new-mexico-large.png", 647 | "map_image_url": "https://cdn.civil.services/us-states/maps/new-mexico-large.png", 648 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/new-mexico.jpg", 649 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/new-mexico.jpg", 650 | "twitter_url": null, 651 | "facebook_url": null 652 | }, 653 | { 654 | "state": "New York", 655 | "slug": "new-york", 656 | "code": "NY", 657 | "nickname": "Empire State", 658 | "website": "http://www.ny.gov", 659 | "admission_date": "1788-07-26", 660 | "admission_number": 11, 661 | "capital_city": "Albany", 662 | "capital_url": "http://www.albanyny.org", 663 | "population": 19651127, 664 | "population_rank": 3, 665 | "constitution_url": "https://www.dos.ny.gov/info/constitution.htm", 666 | "state_flag_url": "https://cdn.civil.services/us-states/flags/new-york-large.png", 667 | "state_seal_url": "https://cdn.civil.services/us-states/seals/new-york-large.png", 668 | "map_image_url": "https://cdn.civil.services/us-states/maps/new-york-large.png", 669 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/new-york.jpg", 670 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/new-york.jpg", 671 | "twitter_url": "https://twitter.com/nygov", 672 | "facebook_url": null 673 | }, 674 | { 675 | "state": "North Carolina", 676 | "slug": "north-carolina", 677 | "code": "NC", 678 | "nickname": "Old North State / Tar Heel State", 679 | "website": "http://www.nc.gov", 680 | "admission_date": "1789-11-21", 681 | "admission_number": 12, 682 | "capital_city": "Raleigh", 683 | "capital_url": "http://www.raleigh-nc.org", 684 | "population": 9848060, 685 | "population_rank": 10, 686 | "constitution_url": "http://statelibrary.dcr.state.nc.us/nc/stgovt/preconst.htm", 687 | "state_flag_url": "https://cdn.civil.services/us-states/flags/north-carolina-large.png", 688 | "state_seal_url": "https://cdn.civil.services/us-states/seals/north-carolina-large.png", 689 | "map_image_url": "https://cdn.civil.services/us-states/maps/north-carolina-large.png", 690 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/north-carolina.jpg", 691 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/north-carolina.jpg", 692 | "twitter_url": "https://twitter.com/NCdotGov", 693 | "facebook_url": null 694 | }, 695 | { 696 | "state": "North Dakota", 697 | "slug": "north-dakota", 698 | "code": "ND", 699 | "nickname": "Peace Garden State / Flickertail State / Roughrider State", 700 | "website": "http://www.nd.gov", 701 | "admission_date": "1889-11-02", 702 | "admission_number": 39, 703 | "capital_city": "Bismarck", 704 | "capital_url": "http://www.bismarck.org", 705 | "population": 723393, 706 | "population_rank": 48, 707 | "constitution_url": "http://www.legis.nd.gov/information/statutes/const-laws.html", 708 | "state_flag_url": "https://cdn.civil.services/us-states/flags/north-dakota-large.png", 709 | "state_seal_url": "https://cdn.civil.services/us-states/seals/north-dakota-large.png", 710 | "map_image_url": "https://cdn.civil.services/us-states/maps/north-dakota-large.png", 711 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/north-dakota.jpg", 712 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/north-dakota.jpg", 713 | "twitter_url": "https://twitter.com/ExperienceND", 714 | "facebook_url": "https://www.facebook.com/ExperienceND" 715 | }, 716 | { 717 | "state": "Ohio", 718 | "slug": "ohio", 719 | "code": "OH", 720 | "nickname": "Buckeye State", 721 | "website": "https://ohio.gov", 722 | "admission_date": "1803-03-01", 723 | "admission_number": 17, 724 | "capital_city": "Columbus", 725 | "capital_url": "http://ci.columbus.oh.us", 726 | "population": 11570808, 727 | "population_rank": 7, 728 | "constitution_url": "http://www.legislature.state.oh.us/constitution.cfm", 729 | "state_flag_url": "https://cdn.civil.services/us-states/flags/ohio-large.png", 730 | "state_seal_url": "https://cdn.civil.services/us-states/seals/ohio-large.png", 731 | "map_image_url": "https://cdn.civil.services/us-states/maps/ohio-large.png", 732 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/ohio.jpg", 733 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/ohio.jpg", 734 | "twitter_url": "https://twitter.com/ohgov", 735 | "facebook_url": null 736 | }, 737 | { 738 | "state": "Oklahoma", 739 | "slug": "oklahoma", 740 | "code": "OK", 741 | "nickname": "Sooner State", 742 | "website": "https://www.ok.gov", 743 | "admission_date": "1907-11-16", 744 | "admission_number": 46, 745 | "capital_city": "Oklahoma City", 746 | "capital_url": "http://www.okc.gov", 747 | "population": 3850568, 748 | "population_rank": 28, 749 | "constitution_url": "http://oklegal.onenet.net/okcon", 750 | "state_flag_url": "https://cdn.civil.services/us-states/flags/oklahoma-large.png", 751 | "state_seal_url": "https://cdn.civil.services/us-states/seals/oklahoma-large.png", 752 | "map_image_url": "https://cdn.civil.services/us-states/maps/oklahoma-large.png", 753 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/oklahoma.jpg", 754 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/oklahoma.jpg", 755 | "twitter_url": "https://twitter.com/okgov", 756 | "facebook_url": "https://www.facebook.com/okgov" 757 | }, 758 | { 759 | "state": "Oregon", 760 | "slug": "oregon", 761 | "code": "OR", 762 | "nickname": "Beaver State", 763 | "website": "http://www.oregon.gov", 764 | "admission_date": "1859-02-14", 765 | "admission_number": 33, 766 | "capital_city": "Salem", 767 | "capital_url": "http://www.cityofsalem.net/Pages/default.aspx", 768 | "population": 3930065, 769 | "population_rank": 27, 770 | "constitution_url": "http://bluebook.state.or.us/state/constitution/constitution.htm", 771 | "state_flag_url": "https://cdn.civil.services/us-states/flags/oregon-large.png", 772 | "state_seal_url": "https://cdn.civil.services/us-states/seals/oregon-large.png", 773 | "map_image_url": "https://cdn.civil.services/us-states/maps/oregon-large.png", 774 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/oregon.jpg", 775 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/oregon.jpg", 776 | "twitter_url": null, 777 | "facebook_url": null 778 | }, 779 | { 780 | "state": "Pennsylvania", 781 | "slug": "pennsylvania", 782 | "code": "PA", 783 | "nickname": "Keystone State", 784 | "website": "http://www.pa.gov", 785 | "admission_date": "1787-12-12", 786 | "admission_number": 2, 787 | "capital_city": "Harrisburg", 788 | "capital_url": "http://harrisburgpa.gov", 789 | "population": 12773801, 790 | "population_rank": 6, 791 | "constitution_url": "http://sites.state.pa.us/PA_Constitution.html", 792 | "state_flag_url": "https://cdn.civil.services/us-states/flags/pennsylvania-large.png", 793 | "state_seal_url": "https://cdn.civil.services/us-states/seals/pennsylvania-large.png", 794 | "map_image_url": "https://cdn.civil.services/us-states/maps/pennsylvania-large.png", 795 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/pennsylvania.jpg", 796 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/pennsylvania.jpg", 797 | "twitter_url": "https://www.facebook.com/visitPA", 798 | "facebook_url": "https://twitter.com/visitPA" 799 | }, 800 | { 801 | "state": "Rhode Island", 802 | "slug": "rhode-island", 803 | "code": "RI", 804 | "nickname": "The Ocean State", 805 | "website": "https://www.ri.gov", 806 | "admission_date": "1790-05-29", 807 | "admission_number": 13, 808 | "capital_city": "Providence", 809 | "capital_url": "http://www.providenceri.com", 810 | "population": 1051511, 811 | "population_rank": 43, 812 | "constitution_url": "http://webserver.rilin.state.ri.us/RiConstitution", 813 | "state_flag_url": "https://cdn.civil.services/us-states/flags/rhode-island-large.png", 814 | "state_seal_url": "https://cdn.civil.services/us-states/seals/rhode-island-large.png", 815 | "map_image_url": "https://cdn.civil.services/us-states/maps/rhode-island-large.png", 816 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/rhode-island.jpg", 817 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/rhode-island.jpg", 818 | "twitter_url": "https://twitter.com/rigov", 819 | "facebook_url": "https://www.facebook.com/RIgov-Rhode-Island-Government-Online-24056655991" 820 | }, 821 | { 822 | "state": "South Carolina", 823 | "slug": "south-carolina", 824 | "code": "SC", 825 | "nickname": "Palmetto State", 826 | "website": "http://www.sc.gov", 827 | "admission_date": "1788-05-23", 828 | "admission_number": 8, 829 | "capital_city": "Columbia", 830 | "capital_url": "http://www.columbiasc.net", 831 | "population": 4774839, 832 | "population_rank": 24, 833 | "constitution_url": "http://www.scstatehouse.gov/scconstitution/scconst.php", 834 | "state_flag_url": "https://cdn.civil.services/us-states/flags/south-carolina-large.png", 835 | "state_seal_url": "https://cdn.civil.services/us-states/seals/south-carolina-large.png", 836 | "map_image_url": "https://cdn.civil.services/us-states/maps/south-carolina-large.png", 837 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/south-carolina.jpg", 838 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/south-carolina.jpg", 839 | "twitter_url": "https://twitter.com/scgov", 840 | "facebook_url": "http://www.facebook.com/pages/SCgov/12752057990" 841 | }, 842 | { 843 | "state": "South Dakota", 844 | "slug": "south-dakota", 845 | "code": "SD", 846 | "nickname": "Mount Rushmore State", 847 | "website": "http://sd.gov", 848 | "admission_date": "1889-11-02", 849 | "admission_number": 40, 850 | "capital_city": "Pierre", 851 | "capital_url": "http://ci.pierre.sd.us", 852 | "population": 844877, 853 | "population_rank": 46, 854 | "constitution_url": "http://legis.sd.gov/statutes/Constitution", 855 | "state_flag_url": "https://cdn.civil.services/us-states/flags/south-dakota-large.png", 856 | "state_seal_url": "https://cdn.civil.services/us-states/seals/south-dakota-large.png", 857 | "map_image_url": "https://cdn.civil.services/us-states/maps/south-dakota-large.png", 858 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/south-dakota.jpg", 859 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/south-dakota.jpg", 860 | "twitter_url": null, 861 | "facebook_url": null 862 | }, 863 | { 864 | "state": "Tennessee", 865 | "slug": "tennessee", 866 | "code": "TN", 867 | "nickname": "Volunteer State", 868 | "website": "https://www.tn.gov", 869 | "admission_date": "1796-06-01", 870 | "admission_number": 16, 871 | "capital_city": "Nashville", 872 | "capital_url": "http://www.nashville.gov", 873 | "population": 6495978, 874 | "population_rank": 17, 875 | "constitution_url": "http://www.capitol.tn.gov/about/docs/TN-Constitution.pdf", 876 | "state_flag_url": "https://cdn.civil.services/us-states/flags/tennessee-large.png", 877 | "state_seal_url": "https://cdn.civil.services/us-states/seals/tennessee-large.png", 878 | "map_image_url": "https://cdn.civil.services/us-states/maps/tennessee-large.png", 879 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/tennessee.jpg", 880 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/tennessee.jpg", 881 | "twitter_url": "https://twitter.com/TNVacation", 882 | "facebook_url": "https://www.facebook.com/tnvacation" 883 | }, 884 | { 885 | "state": "Texas", 886 | "slug": "texas", 887 | "code": "TX", 888 | "nickname": "Lone Star State", 889 | "website": "https://www.texas.gov", 890 | "admission_date": "1845-12-29", 891 | "admission_number": 28, 892 | "capital_city": "Austin", 893 | "capital_url": "http://www.austintexas.gov", 894 | "population": 26448193, 895 | "population_rank": 2, 896 | "constitution_url": "http://www.constitution.legis.state.tx.us", 897 | "state_flag_url": "https://cdn.civil.services/us-states/flags/texas-large.png", 898 | "state_seal_url": "https://cdn.civil.services/us-states/seals/texas-large.png", 899 | "map_image_url": "https://cdn.civil.services/us-states/maps/texas-large.png", 900 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/texas.jpg", 901 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/texas.jpg", 902 | "twitter_url": "https://twitter.com/texasgov", 903 | "facebook_url": "http://www.facebook.com/Texas.gov" 904 | }, 905 | { 906 | "state": "Utah", 907 | "slug": "utah", 908 | "code": "UT", 909 | "nickname": "The Beehive State", 910 | "website": "https://utah.gov", 911 | "admission_date": "1896-01-04", 912 | "admission_number": 45, 913 | "capital_city": "Salt Lake City", 914 | "capital_url": "http://www.slcgov.com", 915 | "population": 2900872, 916 | "population_rank": 33, 917 | "constitution_url": "http://le.utah.gov/UtahCode/chapter.jsp?code=Constitution", 918 | "state_flag_url": "https://cdn.civil.services/us-states/flags/utah-large.png", 919 | "state_seal_url": "https://cdn.civil.services/us-states/seals/utah-large.png", 920 | "map_image_url": "https://cdn.civil.services/us-states/maps/utah-large.png", 921 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/utah.jpg", 922 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/utah.jpg", 923 | "twitter_url": "https://twitter.com/UtahGov", 924 | "facebook_url": "https://www.facebook.com/utahgov" 925 | }, 926 | { 927 | "state": "Vermont", 928 | "slug": "vermont", 929 | "code": "VT", 930 | "nickname": "Green Mountain State", 931 | "website": "http://vermont.gov", 932 | "admission_date": "1791-03-04", 933 | "admission_number": 14, 934 | "capital_city": "Montpelier", 935 | "capital_url": "http://www.montpelier-vt.org", 936 | "population": 626630, 937 | "population_rank": 49, 938 | "constitution_url": "http://www.leg.state.vt.us/statutes/const2.htm", 939 | "state_flag_url": "https://cdn.civil.services/us-states/flags/vermont-large.png", 940 | "state_seal_url": "https://cdn.civil.services/us-states/seals/vermont-large.png", 941 | "map_image_url": "https://cdn.civil.services/us-states/maps/vermont-large.png", 942 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/vermont.jpg", 943 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/vermont.jpg", 944 | "twitter_url": "https://twitter.com/vermontgov", 945 | "facebook_url": "https://www.facebook.com/MyVermont" 946 | }, 947 | { 948 | "state": "Virginia", 949 | "slug": "virginia", 950 | "code": "VA", 951 | "nickname": "Old Dominion State", 952 | "website": "https://www.virginia.gov", 953 | "admission_date": "1788-06-25", 954 | "admission_number": 10, 955 | "capital_city": "Richmond", 956 | "capital_url": "http://www.richmondgov.com", 957 | "population": 8260405, 958 | "population_rank": 12, 959 | "constitution_url": "http://hodcap.state.va.us/publications/Constitution-01-13.pdf", 960 | "state_flag_url": "https://cdn.civil.services/us-states/flags/virginia-large.png", 961 | "state_seal_url": "https://cdn.civil.services/us-states/seals/virginia-large.png", 962 | "map_image_url": "https://cdn.civil.services/us-states/maps/virginia-large.png", 963 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/virginia.jpg", 964 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/virginia.jpg", 965 | "twitter_url": null, 966 | "facebook_url": null 967 | }, 968 | { 969 | "state": "Washington", 970 | "slug": "washington", 971 | "code": "WA", 972 | "nickname": "The Evergreen State", 973 | "website": "http://www.wa.gov", 974 | "admission_date": "1889-11-11", 975 | "admission_number": 42, 976 | "capital_city": "Olympia", 977 | "capital_url": "http://www.ci.olympia.wa.us", 978 | "population": 6971406, 979 | "population_rank": 13, 980 | "constitution_url": "http://www.leg.wa.gov/lawsandagencyrules/pages/constitution.aspx", 981 | "state_flag_url": "https://cdn.civil.services/us-states/flags/washington-large.png", 982 | "state_seal_url": "https://cdn.civil.services/us-states/seals/washington-large.png", 983 | "map_image_url": "https://cdn.civil.services/us-states/maps/washington-large.png", 984 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/washington.jpg", 985 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/washington.jpg", 986 | "twitter_url": "https://twitter.com/wagov", 987 | "facebook_url": "" 988 | }, 989 | { 990 | "state": "West Virginia", 991 | "slug": "west-virginia", 992 | "code": "WV", 993 | "nickname": "Mountain State", 994 | "website": "http://www.wv.gov", 995 | "admission_date": "1863-06-20", 996 | "admission_number": 35, 997 | "capital_city": "Charleston", 998 | "capital_url": "http://www.cityofcharleston.org", 999 | "population": 1854304, 1000 | "population_rank": 38, 1001 | "constitution_url": "http://www.legis.state.wv.us/WVCODE/WV_CON.cfm", 1002 | "state_flag_url": "https://cdn.civil.services/us-states/flags/west-virginia-large.png", 1003 | "state_seal_url": "https://cdn.civil.services/us-states/seals/west-virginia-large.png", 1004 | "map_image_url": "https://cdn.civil.services/us-states/maps/west-virginia-large.png", 1005 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/west-virginia.jpg", 1006 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/west-virginia.jpg", 1007 | "twitter_url": "https://twitter.com/wvgov", 1008 | "facebook_url": "https://www.facebook.com/wvgov" 1009 | }, 1010 | { 1011 | "state": "Wisconsin", 1012 | "slug": "wisconsin", 1013 | "code": "WI", 1014 | "nickname": "Badger State", 1015 | "website": "https://www.wisconsin.gov", 1016 | "admission_date": "1848-05-29", 1017 | "admission_number": 30, 1018 | "capital_city": "Madison", 1019 | "capital_url": "http://www.ci.madison.wi.us", 1020 | "population": 5742713, 1021 | "population_rank": 20, 1022 | "constitution_url": "http://www.legis.state.wi.us/rsb/2wiscon.html", 1023 | "state_flag_url": "https://cdn.civil.services/us-states/flags/wisconsin-large.png", 1024 | "state_seal_url": "https://cdn.civil.services/us-states/seals/wisconsin-large.png", 1025 | "map_image_url": "https://cdn.civil.services/us-states/maps/wisconsin-large.png", 1026 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/wisconsin.jpg", 1027 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/wisconsin.jpg", 1028 | "twitter_url": null, 1029 | "facebook_url": null 1030 | }, 1031 | { 1032 | "state": "Wyoming", 1033 | "slug": "wyoming", 1034 | "code": "WY", 1035 | "nickname": "Equality State", 1036 | "website": "http://www.wyo.gov", 1037 | "admission_date": "1890-07-10", 1038 | "admission_number": 44, 1039 | "capital_city": "Cheyenne", 1040 | "capital_url": "http://www.cheyennecity.org", 1041 | "population": 582658, 1042 | "population_rank": 50, 1043 | "constitution_url": "http://legisweb.state.wy.us/statutes/constitution.aspx?file=titles/97Title97.htm", 1044 | "state_flag_url": "https://cdn.civil.services/us-states/flags/wyoming-large.png", 1045 | "state_seal_url": "https://cdn.civil.services/us-states/seals/wyoming-large.png", 1046 | "map_image_url": "https://cdn.civil.services/us-states/maps/wyoming-large.png", 1047 | "landscape_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/landscape/wyoming.jpg", 1048 | "skyline_background_url": "https://cdn.civil.services/us-states/backgrounds/1280x720/skyline/wyoming.jpg", 1049 | "twitter_url": null, 1050 | "facebook_url": null 1051 | } 1052 | ] -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss" 2 | 3 | const config = { 4 | darkMode: ["class"], 5 | content: [ 6 | './pages/**/*.{ts,tsx}', 7 | './components/**/*.{ts,tsx}', 8 | './app/**/*.{ts,tsx}', 9 | './src/**/*.{ts,tsx}', 10 | ], 11 | prefix: "", 12 | theme: { 13 | container: { 14 | center: true, 15 | padding: "2rem", 16 | screens: { 17 | "2xl": "1400px", 18 | }, 19 | }, 20 | extend: { 21 | colors: { 22 | border: "hsl(var(--border))", 23 | input: "hsl(var(--input))", 24 | ring: "hsl(var(--ring))", 25 | background: "hsl(var(--background))", 26 | foreground: "hsl(var(--foreground))", 27 | primary: { 28 | DEFAULT: "hsl(var(--primary))", 29 | foreground: "hsl(var(--primary-foreground))", 30 | }, 31 | secondary: { 32 | DEFAULT: "hsl(var(--secondary))", 33 | foreground: "hsl(var(--secondary-foreground))", 34 | }, 35 | destructive: { 36 | DEFAULT: "hsl(var(--destructive))", 37 | foreground: "hsl(var(--destructive-foreground))", 38 | }, 39 | muted: { 40 | DEFAULT: "hsl(var(--muted))", 41 | foreground: "hsl(var(--muted-foreground))", 42 | }, 43 | accent: { 44 | DEFAULT: "hsl(var(--accent))", 45 | foreground: "hsl(var(--accent-foreground))", 46 | }, 47 | popover: { 48 | DEFAULT: "hsl(var(--popover))", 49 | foreground: "hsl(var(--popover-foreground))", 50 | }, 51 | card: { 52 | DEFAULT: "hsl(var(--card))", 53 | foreground: "hsl(var(--card-foreground))", 54 | }, 55 | }, 56 | borderRadius: { 57 | lg: "var(--radius)", 58 | md: "calc(var(--radius) - 2px)", 59 | sm: "calc(var(--radius) - 4px)", 60 | }, 61 | keyframes: { 62 | "accordion-down": { 63 | from: { height: "0" }, 64 | to: { height: "var(--radix-accordion-content-height)" }, 65 | }, 66 | "accordion-up": { 67 | from: { height: "var(--radix-accordion-content-height)" }, 68 | to: { height: "0" }, 69 | }, 70 | }, 71 | animation: { 72 | "accordion-down": "accordion-down 0.2s ease-out", 73 | "accordion-up": "accordion-up 0.2s ease-out", 74 | }, 75 | }, 76 | }, 77 | plugins: [require("tailwindcss-animate")], 78 | } satisfies Config 79 | 80 | export default config -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | --------------------------------------------------------------------------------