This is a Next.js project bootstrapped with create-next-app.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen 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.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
- Modify your TypeScript schema in
app/db/schema.ts - Run
npx drizzle-kit generateto create a new migration file - Review the generated SQL to make sure it looks correct
- Run
npx drizzle-kit migrateto apply the migration to your database
It is common to end up in a situation where the migration state gets out of sync with the actual database, for example if you manually modify the database, edit a migration file after it has been applied, or generate a migration and then change the schema again before applying it.
When things go wrong, you will typically see errors like "relation already exists" or "column does not exist" when running drizzle-kit migrate. This happens because Drizzle's migration tracker thinks the database is in one state, but the actual database is in another.
During development, when the database does not contain any important data, the simplest recovery strategy is to start fresh. You can do this in two steps:
First, remove Drizzle's migration tracking from the database and drop all the tables you have created:
DROP TABLE IF EXISTS drizzle.__drizzle_migrations CASCADE;
DROP TABLE IF EXISTS notes CASCADE;
DROP TABLE IF EXISTS users CASCADE;Second, remove the local migration history so that Drizzle Kit forgets all previously generated migrations:
npx drizzle-kit dropThe command drizzle-kit drop lets you select which migration entries to remove from the local journal. After dropping them, you can regenerate and reapply everything cleanly:
npx drizzle-kit generate
npx drizzle-kit migrateThis "nuclear option" is perfectly fine during development. In production, however, you should never drop tables or delete migration history, since that means losing real user data. In a production environment, the correct approach is to always move forward: write a new migration that fixes the problem, rather than trying to undo previous ones.
There are several things you should do to set up the tests for your project.
Copy the directories tests and .github from this repository to the root of your submission repository.
Replace the file drizzle.config.ts in your repository with the one you find in this directory.
Install the following:
npm install --save-dev @playwright/test dotenv
npx playwright installAdd scripts to package.json:
{
// ...
scripts:{
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
}
}
Create a new Neon DB in Vercel
Set up environment variables for your GitHub repository:
Click Settings → Secrets and variables → Actions
- Add these repository secrets:
- DATABASE_URL - Your Neon test database URL
- NEXTAUTH_SECRET - any_random_character_sequence
- NEXTAUTH_URL - Use http://localhost:3000
Create file .env.local to your submission repository with following
DATABASE_URL=your_neon_test_database_URL
NEXTAUTH_SECRET=any_random_character_sequence
NEXTAUTH_URL=http://localhost:3000You can run tests locally with npm run test:e2e
Tests are making several assumptions on your UI:
- form controls must have labels "Username", "Password", "Title", etc.
- urls: "login", "blogs", "me", etc.
- test IDs
Eg. the below tests assumes that the url of the creation form is /blogs/new, form controls have the labels and eg. the creation button has test id create-blog-button:
test('logged in user can create a blog', async ({ page }) => {
await loginUser(page, 'testuser', 'testpass123');
await page.goto('/blogs/new');
await page.getByLabel('Title', { exact: true }).fill('Test Blog');
await page.getByLabel('Author', { exact: true }).fill('Test Author');
await page.getByLabel('URL', { exact: true }).fill('http://testblog.com');
await page.getByTestId('create-blog-button').click();
// Should redirect to blogs page
await expect(page).toHaveURL('/blogs');
// Should show success notification
await expect(page.getByTestId('notification')).toBeVisible();
// Blog should appear in the list
await expect(page.getByTestId('blogs-list')).toContainText('Test Blog');
});The test id is added to the button with prop data-testid:
<button
type="submit"
data-testid="create-blog-button"
className="w-full py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors font-semibold"
{...props}
>
Create
</button>See the tests for more!
Commit .github to your submission repository and push it to GitHub